GramJs: Fix ESLint errors (#1070)

This commit is contained in:
Alexander Zinchuk 2021-05-21 14:50:12 +03:00
parent 4faa7563aa
commit b36ec8cf44
46 changed files with 330 additions and 296 deletions

View File

@ -20,6 +20,10 @@
], ],
"no-bitwise": "off", "no-bitwise": "off",
"no-underscore-dangle": "off", "no-underscore-dangle": "off",
"no-null/no-null": "off" "no-continue": "off",
"no-restricted-syntax": "off",
"class-methods-use-this": "off",
"max-classes-per-file": "off",
"camelcase": "error"
} }
} }

View File

@ -310,7 +310,7 @@ function makeCRCTable() {
return crcTable; return crcTable;
} }
let crcTable = null; let crcTable;
function crc32(buf) { function crc32(buf) {
if (!crcTable) { if (!crcTable) {

View File

@ -1,5 +1,4 @@
const BigInt = require('big-integer'); const BigInt = require('big-integer');
const Factorizator = require('./crypto/Factorizator');
const { constructors } = require('./tl'); const { constructors } = require('./tl');
const { const {
readBigIntFromBuffer, readBigIntFromBuffer,
@ -148,7 +147,7 @@ function xor(a, b) {
const length = Math.min(a.length, b.length); const length = Math.min(a.length, b.length);
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
a[i] = a[i] ^ b[i]; a[i] ^= b[i];
} }
return a; return a;

View File

@ -1,16 +1,9 @@
const { constructors } = require('./tl'); const { constructors } = require('./tl');
const USERNAME_RE = new RegExp('@|(?:https?:\\/\\/)?(?:www\\.)?' // eslint-disable-next-line max-len
+ '(?:telegram\\.(?:me|dog)|t\\.me)\\/(@|joinchat\\/)?');
const JPEG_HEADER = Buffer.from('ffd8ffe000104a46494600010100000100010000ffdb004300281c1e231e19282321232d2b28303c64413c37373c7b585d4964918099968f808c8aa0b4e6c3a0aadaad8a8cc8ffcbdaeef5ffffff9bc1fffffffaffe6fdfff8ffdb0043012b2d2d3c353c76414176f8a58ca5f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8ffc00011080000000003012200021101031101ffc4001f0000010501010101010100000000000000000102030405060708090a0bffc400b5100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9faffc4001f0100030101010101010101010000000000000102030405060708090a0bffc400b51100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00', 'hex'); const JPEG_HEADER = Buffer.from('ffd8ffe000104a46494600010100000100010000ffdb004300281c1e231e19282321232d2b28303c64413c37373c7b585d4964918099968f808c8aa0b4e6c3a0aadaad8a8cc8ffcbdaeef5ffffff9bc1fffffffaffe6fdfff8ffdb0043012b2d2d3c353c76414176f8a58ca5f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8ffc00011080000000003012200021101031101ffc4001f0000010501010101010100000000000000000102030405060708090a0bffc400b5100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9faffc4001f0100030101010101010101010000000000000102030405060708090a0bffc400b51100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00', 'hex');
const JPEG_FOOTER = Buffer.from('ffd9', 'hex'); const JPEG_FOOTER = Buffer.from('ffd9', 'hex');
const TG_JOIN_RE = new RegExp('tg:\\/\\/(join)\\?invite=');
const VALID_USERNAME_RE = new RegExp('^([a-z]((?!__)[\\w\\d]){3,30}[a-z\\d]|gif|vid|'
+ 'pic|bing|wiki|imdb|bold|vote|like|coub)$');
function _raiseCastFail(entity, target) { function _raiseCastFail(entity, target) {
throw new Error(`Cannot cast ${entity.className} to any kind of ${target}`); throw new Error(`Cannot cast ${entity.className} to any kind of ${target}`);
} }
@ -111,6 +104,7 @@ function getInputPeer(entity, allowSelf = true, checkHash = true) {
} }
_raiseCastFail(entity, 'InputPeer'); _raiseCastFail(entity, 'InputPeer');
return undefined;
} }
/** /**
@ -252,7 +246,8 @@ function getInputMessage(message) {
/** /**
* Adds the JPG header and footer to a stripped image. * Adds the JPG header and footer to a stripped image.
* Ported from https://github.com/telegramdesktop/tdesktop/blob/bec39d89e19670eb436dc794a8f20b657cb87c71/Telegram/SourceFiles/ui/image/image.cpp#L225 * Ported from https://github.com/telegramdesktop/
* tdesktop/blob/bec39d89e19670eb436dc794a8f20b657cb87c71/Telegram/SourceFiles/ui/image/image.cpp#L225
* @param stripped{Buffer} * @param stripped{Buffer}
* @returns {Buffer} * @returns {Buffer}
@ -263,7 +258,9 @@ function strippedPhotoToJpg(stripped) {
return stripped; return stripped;
} }
const header = Buffer.from(JPEG_HEADER); const header = Buffer.from(JPEG_HEADER);
// eslint-disable-next-line prefer-destructuring
header[164] = stripped[1]; header[164] = stripped[1];
// eslint-disable-next-line prefer-destructuring
header[166] = stripped[2]; header[166] = stripped[2];
return Buffer.concat([header, stripped.slice(3), JPEG_FOOTER]); return Buffer.concat([header, stripped.slice(3), JPEG_FOOTER]);
} }
@ -502,8 +499,8 @@ function _getEntityPair(entityId, entities, cache, getInputPeer = getInputPeer)
*/ */
function getMessageId(message) { function getMessageId(message) {
if (message === null || message === undefined) { if (message === undefined) {
return null; return undefined;
} }
if (typeof message === 'number') { if (typeof message === 'number') {
return message; return message;
@ -515,15 +512,6 @@ function getMessageId(message) {
} }
/**
* Parses the given phone, or returns `None` if it's invalid.
* @param phone
*/
function parsePhone(phone) {
return phone.toString()
.replace(/[+()\s-]/gm, '');
}
/** /**
Parses the given username or channel access hash, given Parses the given username or channel access hash, given
a string, username or URL. Returns a tuple consisting of a string, username or URL. Returns a tuple consisting of
@ -617,7 +605,7 @@ function isListLike(item) {
) )
} }
*/ */
function getDC(dcId, cdn = false) { function getDC(dcId) {
switch (dcId) { switch (dcId) {
case 1: case 1:
return { return {

View File

@ -1,4 +1,5 @@
import TelegramClient from './TelegramClient'; import TelegramClient from './TelegramClient';
// eslint-disable-next-line import/no-named-default
import { default as Api } from '../tl/api'; import { default as Api } from '../tl/api';
import { generateRandomBytes } from '../Helpers'; import { generateRandomBytes } from '../Helpers';
import { computeCheck, computeDigest } from '../Password'; import { computeCheck, computeDigest } from '../Password';
@ -100,7 +101,8 @@ export async function updateTwoFaSettings(
})); }));
} catch (e) { } catch (e) {
if (e instanceof errors.EmailUnconfirmedError) { if (e instanceof errors.EmailUnconfirmedError) {
while (1) { // eslint-disable-next-line no-constant-condition
while (true) {
try { try {
const code = await emailCodeCallback!(e.codeLength); const code = await emailCodeCallback!(e.codeLength);

View File

@ -4,7 +4,6 @@ const { sleep } = require('../Helpers');
const errors = require('../errors'); const errors = require('../errors');
const MemorySession = require('../sessions/Memory'); const MemorySession = require('../sessions/Memory');
const Helpers = require('../Helpers'); const Helpers = require('../Helpers');
const { BinaryWriter } = require('../extensions');
const utils = require('../Utils'); const utils = require('../Utils');
const Session = require('../sessions/Abstract'); const Session = require('../sessions/Abstract');
const { LAYER } = require('../tl/AllTLObjects'); const { LAYER } = require('../tl/AllTLObjects');
@ -13,7 +12,6 @@ const {
requests, requests,
} = require('../tl'); } = require('../tl');
const MTProtoSender = require('../network/MTProtoSender'); const MTProtoSender = require('../network/MTProtoSender');
const { UpdateConnectionState } = require('../network');
const { ConnectionTCPObfuscated } = require('../network/connection/TCPObfuscated'); const { ConnectionTCPObfuscated } = require('../network/connection/TCPObfuscated');
const { const {
authFlow, authFlow,
@ -35,7 +33,7 @@ class TelegramClient {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
connection: ConnectionTCPObfuscated, connection: ConnectionTCPObfuscated,
useIPV6: false, useIPV6: false,
proxy: null, proxy: undefined,
timeout: 10, timeout: 10,
requestRetries: 5, requestRetries: 5,
connectionRetries: Infinity, connectionRetries: Infinity,
@ -43,9 +41,9 @@ class TelegramClient {
autoReconnect: true, autoReconnect: true,
sequentialUpdates: false, sequentialUpdates: false,
floodSleepLimit: 60, floodSleepLimit: 60,
deviceModel: null, deviceModel: undefined,
systemVersion: null, systemVersion: undefined,
appVersion: null, appVersion: undefined,
langCode: 'en', langCode: 'en',
systemLangCode: 'en', systemLangCode: 'en',
baseLogger: 'gramjs', baseLogger: 'gramjs',
@ -91,7 +89,7 @@ class TelegramClient {
this._phoneCodeHash = {}; this._phoneCodeHash = {};
this.session = session; this.session = session;
// this._entityCache = EntityCache(); // this._entityCache = EntityCache();
this.apiId = parseInt(apiId); this.apiId = parseInt(apiId, 10);
this.apiHash = apiHash; this.apiHash = apiHash;
this._requestRetries = args.requestRetries; this._requestRetries = args.requestRetries;
@ -123,14 +121,14 @@ class TelegramClient {
langPack: '', // this should be left empty. langPack: '', // this should be left empty.
systemLangCode: args.systemLangCode, systemLangCode: args.systemLangCode,
query: x, query: x,
proxy: null, // no proxies yet. proxy: undefined, // no proxies yet.
}), }),
}); });
}; };
this._args = args; this._args = args;
// These will be set later // These will be set later
this._config = null; this._config = undefined;
this.phoneCodeHashes = []; this.phoneCodeHashes = [];
this._borrowedSenderPromises = {}; this._borrowedSenderPromises = {};
this._additionalDcsDisabled = args.additionalDcsDisabled; this._additionalDcsDisabled = args.additionalDcsDisabled;
@ -178,7 +176,8 @@ class TelegramClient {
await this.session.load(); await this.session.load();
if (!this.session.serverAddress || (this.session.serverAddress.includes(':') !== this._useIPV6)) { if (!this.session.serverAddress || (this.session.serverAddress.includes(':') !== this._useIPV6)) {
this.session.setDC(DEFAULT_DC_ID, this._useIPV6 ? DEFAULT_IPV6_IP : DEFAULT_IPV4_IP, this._args.useWSS ? 443 : 80); this.session.setDC(DEFAULT_DC_ID, this._useIPV6
? DEFAULT_IPV6_IP : DEFAULT_IPV4_IP, this._args.useWSS ? 443 : 80);
} }
} }
@ -208,7 +207,7 @@ class TelegramClient {
try { try {
await this.invoke(new requests.updates.GetState()); await this.invoke(new requests.updates.GetState());
} catch (e) { } catch (e) {
// we don't care about errors here
} }
} }
} }
@ -230,6 +229,7 @@ class TelegramClient {
if (sender) { if (sender) {
return sender.disconnect(); return sender.disconnect();
} }
return undefined;
}); });
}), }),
); );
@ -253,13 +253,13 @@ class TelegramClient {
this.session.setDC(newDc, DC.ipAddress, DC.port); this.session.setDC(newDc, DC.ipAddress, DC.port);
// authKey's are associated with a server, which has now changed // authKey's are associated with a server, which has now changed
// so it's not valid anymore. Set to None to force recreating it. // so it's not valid anymore. Set to None to force recreating it.
await this._sender.authKey.setKey(null); await this._sender.authKey.setKey(undefined);
this.session.setAuthKey(null); this.session.setAuthKey(undefined);
await this.disconnect(); await this.disconnect();
return this.connect(); return this.connect();
} }
async _authKeyCallback(authKey, dcId) { _authKeyCallback(authKey, dcId) {
this.session.setAuthKey(authKey, dcId); this.session.setAuthKey(authKey, dcId);
} }
@ -270,7 +270,7 @@ class TelegramClient {
delete this._borrowedSenderPromises[dcId]; delete this._borrowedSenderPromises[dcId];
} }
async _borrowExportedSender(dcId) { _borrowExportedSender(dcId) {
if (this._additionalDcsDisabled) { if (this._additionalDcsDisabled) {
return undefined; return undefined;
} }
@ -326,7 +326,7 @@ class TelegramClient {
await sender.disconnect(); await sender.disconnect();
} }
} }
return null; return undefined;
} }
// end region // end region
@ -345,18 +345,15 @@ class TelegramClient {
* @param [args[workers] {number}] * @param [args[workers] {number}]
* @returns {Promise<Buffer>} * @returns {Promise<Buffer>}
*/ */
async downloadFile(inputLocation, args = {}) { downloadFile(inputLocation, args = {}) {
return downloadFile(this, inputLocation, args); return downloadFile(this, inputLocation, args);
} }
async downloadMedia(messageOrMedia, args) { downloadMedia(messageOrMedia, args) {
let date;
let media; let media;
if (messageOrMedia instanceof constructors.Message) { if (messageOrMedia instanceof constructors.Message) {
date = messageOrMedia.date;
media = messageOrMedia.media; media = messageOrMedia.media;
} else { } else {
date = new Date().getTime();
media = messageOrMedia; media = messageOrMedia;
} }
if (typeof media === 'string') { if (typeof media === 'string') {
@ -377,9 +374,10 @@ class TelegramClient {
} else if (media instanceof constructors.WebDocument || media instanceof constructors.WebDocumentNoProxy) { } else if (media instanceof constructors.WebDocument || media instanceof constructors.WebDocumentNoProxy) {
return this._downloadWebDocument(media, args); return this._downloadWebDocument(media, args);
} }
return undefined;
} }
async downloadProfilePhoto(entity, isBig = false) { downloadProfilePhoto(entity, isBig = false) {
// ('User', 'Chat', 'UserFull', 'ChatFull') // ('User', 'Chat', 'UserFull', 'ChatFull')
const ENTITIES = [0x2da17977, 0xc5af5d94, 0x1f4661b9, 0xd49a2697]; const ENTITIES = [0x2da17977, 0xc5af5d94, 0x1f4661b9, 0xd49a2697];
// ('InputPeer', 'InputUser', 'InputChannel') // ('InputPeer', 'InputUser', 'InputChannel')
@ -393,7 +391,7 @@ class TelegramClient {
if (!entity.photo) { if (!entity.photo) {
// Special case: may be a ChatFull with photo:Photo // Special case: may be a ChatFull with photo:Photo
if (!entity.chatPhoto) { if (!entity.chatPhoto) {
return null; return undefined;
} }
return this._downloadPhoto( return this._downloadPhoto(
@ -417,32 +415,14 @@ class TelegramClient {
// as input location, because then this method would be able // as input location, because then this method would be able
// to "download the profile photo of a message", i.e. its // to "download the profile photo of a message", i.e. its
// media which should be done with `download_media` instead. // media which should be done with `download_media` instead.
return null; return undefined;
}
try {
return this.downloadFile(loc, {
dcId,
});
} catch (e) {
// TODO this should never raise
throw e;
/* if (e.message === 'LOCATION_INVALID') {
const ie = await this.getInputEntity(entity)
if (ie instanceof constructors.InputPeerChannel) {
const full = await this.invoke(new requests.channels.GetFullChannel({
channel: ie,
}))
return this._downloadPhoto(full.fullChat.chatPhoto, { sizeType })
} else {
return null
}
} else {
throw e
} */
} }
return this.downloadFile(loc, {
dcId,
});
} }
async downloadStickerSetThumb(stickerSet) { downloadStickerSetThumb(stickerSet) {
if (!stickerSet.thumbs || !stickerSet.thumbs.length) { if (!stickerSet.thumbs || !stickerSet.thumbs.length) {
return undefined; return undefined;
} }
@ -462,7 +442,7 @@ class TelegramClient {
_pickFileSize(sizes, sizeType) { _pickFileSize(sizes, sizeType) {
if (!sizeType || !sizes || !sizes.length) { if (!sizeType || !sizes || !sizes.length) {
return null; return undefined;
} }
const indexOfSize = sizeTypes.indexOf(sizeType); const indexOfSize = sizeTypes.indexOf(sizeType);
let size; let size;
@ -472,7 +452,7 @@ class TelegramClient {
return size; return size;
} }
} }
return null; return undefined;
} }
@ -487,16 +467,16 @@ class TelegramClient {
return data; return data;
} }
async _downloadPhoto(photo, args) { _downloadPhoto(photo, args) {
if (photo instanceof constructors.MessageMediaPhoto) { if (photo instanceof constructors.MessageMediaPhoto) {
photo = photo.photo; photo = photo.photo;
} }
if (!(photo instanceof constructors.Photo)) { if (!(photo instanceof constructors.Photo)) {
return; return undefined;
} }
const size = this._pickFileSize(photo.sizes, args.sizeType); const size = this._pickFileSize(photo.sizes, args.sizeType);
if (!size || (size instanceof constructors.PhotoSizeEmpty)) { if (!size || (size instanceof constructors.PhotoSizeEmpty)) {
return; return undefined;
} }
if (size instanceof constructors.PhotoCachedSize || size instanceof constructors.PhotoStrippedSize) { if (size instanceof constructors.PhotoCachedSize || size instanceof constructors.PhotoStrippedSize) {
@ -517,22 +497,23 @@ class TelegramClient {
); );
} }
async _downloadDocument(doc, args) { _downloadDocument(doc, args) {
if (doc instanceof constructors.MessageMediaDocument) { if (doc instanceof constructors.MessageMediaDocument) {
doc = doc.document; doc = doc.document;
} }
if (!(doc instanceof constructors.Document)) { if (!(doc instanceof constructors.Document)) {
return; return undefined;
} }
let size = null; let size;
if (args.sizeType) { if (args.sizeType) {
size = doc.thumbs ? this._pickFileSize(doc.thumbs, args.sizeType) : null; size = doc.thumbs ? this._pickFileSize(doc.thumbs, args.sizeType) : undefined;
if (!size && doc.mimeType.startsWith('video/')) { if (!size && doc.mimeType.startsWith('video/')) {
return; return undefined;
} }
if (size && (size instanceof constructors.PhotoCachedSize || size instanceof constructors.PhotoStrippedSize)) { if (size && (size instanceof constructors.PhotoCachedSize
|| size instanceof constructors.PhotoStrippedSize)) {
return this._downloadCachedPhotoSize(size); return this._downloadCachedPhotoSize(size);
} }
} }
@ -555,10 +536,12 @@ class TelegramClient {
); );
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_downloadContact(media, args) { _downloadContact(media, args) {
throw new Error('not implemented'); throw new Error('not implemented');
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_downloadWebDocument(media, args) { _downloadWebDocument(media, args) {
throw new Error('not implemented'); throw new Error('not implemented');
} }
@ -601,7 +584,8 @@ class TelegramClient {
} else if (e instanceof errors.PhoneMigrateError || e instanceof errors.NetworkMigrateError } else if (e instanceof errors.PhoneMigrateError || e instanceof errors.NetworkMigrateError
|| e instanceof errors.UserMigrateError) { || e instanceof errors.UserMigrateError) {
this._log.info(`Phone migrated to ${e.newDc}`); this._log.info(`Phone migrated to ${e.newDc}`);
const shouldRaise = e instanceof errors.PhoneMigrateError || e instanceof errors.NetworkMigrateError; const shouldRaise = e instanceof errors.PhoneMigrateError
|| e instanceof errors.NetworkMigrateError;
if (shouldRaise && await checkAuthorization(this)) { if (shouldRaise && await checkAuthorization(this)) {
throw e; throw e;
} }
@ -619,7 +603,10 @@ class TelegramClient {
return (await this.invoke(new requests.users return (await this.invoke(new requests.users
.GetUsers({ id: [new constructors.InputUserSelf()] })))[0]; .GetUsers({ id: [new constructors.InputUserSelf()] })))[0];
} catch (e) { } catch (e) {
this._log.warn('error while getting me');
this._log.warn(e);
} }
return undefined;
} }
async start(authParams) { async start(authParams) {
@ -666,9 +653,9 @@ class TelegramClient {
this._processUpdate(u, update.updates, entities); this._processUpdate(u, update.updates, entities);
} }
} else if (update instanceof constructors.UpdateShort) { } else if (update instanceof constructors.UpdateShort) {
this._processUpdate(update.update, null); this._processUpdate(update.update, undefined);
} else { } else {
this._processUpdate(update, null); this._processUpdate(update, undefined);
} }
// TODO add caching // TODO add caching
// this._stateCache.update(update) // this._stateCache.update(update)
@ -915,10 +902,10 @@ class TelegramClient {
} }
*/ */
async _dispatchUpdate(args = { async _dispatchUpdate(args = {
update: null, update: undefined,
others: null, others: undefined,
channelId: null, channelId: undefined,
ptsDate: null, ptsDate: undefined,
}) { }) {
for (const [builder, callback] of this._eventBuilders) { for (const [builder, callback] of this._eventBuilders) {
const event = builder.build(args.update); const event = builder.build(args.update);
@ -938,7 +925,7 @@ class TelegramClient {
} }
} }
async function timeout(promise, ms) { function timeout(promise, ms) {
return Promise.race([ return Promise.race([
promise, promise,
Helpers.sleep(ms) Helpers.sleep(ms)
@ -959,6 +946,7 @@ async function attempts(cb, times, pause) {
await Helpers.sleep(pause); await Helpers.sleep(pause);
} }
} }
return undefined;
} }
module.exports = TelegramClient; module.exports = TelegramClient;

View File

@ -1,3 +1,4 @@
// eslint-disable-next-line import/no-named-default
import { default as Api } from '../tl/api'; import { default as Api } from '../tl/api';
import TelegramClient from './TelegramClient'; import TelegramClient from './TelegramClient';
import utils from '../Utils'; import utils from '../Utils';
@ -55,7 +56,8 @@ async function signInUser(
let phoneCodeHash; let phoneCodeHash;
let isCodeViaApp = false; let isCodeViaApp = false;
while (1) { // eslint-disable-next-line no-constant-condition
while (true) {
try { try {
if (typeof authParams.phoneNumber === 'function') { if (typeof authParams.phoneNumber === 'function') {
try { try {
@ -92,6 +94,7 @@ async function signInUser(
let isRegistrationRequired = false; let isRegistrationRequired = false;
let termsOfService; let termsOfService;
// eslint-disable-next-line no-constant-condition
while (1) { while (1) {
try { try {
try { try {
@ -132,6 +135,7 @@ async function signInUser(
} }
if (isRegistrationRequired) { if (isRegistrationRequired) {
// eslint-disable-next-line no-constant-condition
while (1) { while (1) {
try { try {
const [firstName, lastName] = await authParams.firstAndLastNames(); const [firstName, lastName] = await authParams.firstAndLastNames();
@ -168,6 +172,7 @@ async function signInUserWithQrCode(
let isScanningComplete = false; let isScanningComplete = false;
const inputPromise = (async () => { const inputPromise = (async () => {
// eslint-disable-next-line no-constant-condition
while (1) { while (1) {
if (isScanningComplete) { if (isScanningComplete) {
break; break;
@ -228,7 +233,8 @@ async function signInUserWithQrCode(
token: result2.token, token: result2.token,
})); }));
if (migratedResult instanceof Api.auth.LoginTokenSuccess && migratedResult.authorization instanceof Api.auth.Authorization) { if (migratedResult instanceof Api.auth.LoginTokenSuccess
&& migratedResult.authorization instanceof Api.auth.Authorization) {
return migratedResult.authorization.user; return migratedResult.authorization.user;
} }
} }
@ -241,6 +247,7 @@ async function signInUserWithQrCode(
} }
// This is a workaround for TypeScript (never actually reached) // This is a workaround for TypeScript (never actually reached)
// eslint-disable-next-line no-throw-literal
throw undefined; throw undefined;
} }
@ -288,6 +295,7 @@ async function sendCode(
async function signInWithPassword( async function signInWithPassword(
client: TelegramClient, apiCredentials: ApiCredentials, authParams: UserAuthParams, client: TelegramClient, apiCredentials: ApiCredentials, authParams: UserAuthParams,
): Promise<Api.TypeUser> { ): Promise<Api.TypeUser> {
// eslint-disable-next-line no-constant-condition
while (1) { while (1) {
try { try {
const passwordSrpResult = await client.invoke(new Api.account.GetPassword()); const passwordSrpResult = await client.invoke(new Api.account.GetPassword());
@ -307,6 +315,7 @@ async function signInWithPassword(
} }
} }
// eslint-disable-next-line no-unreachable
return undefined!; // Never reached (TypeScript fix) return undefined!; // Never reached (TypeScript fix)
} }

View File

@ -1,3 +1,4 @@
// eslint-disable-next-line import/no-named-default
import { default as Api } from '../tl/api'; import { default as Api } from '../tl/api';
import TelegramClient from './TelegramClient'; import TelegramClient from './TelegramClient';
import { getAppropriatedPartSize } from '../Utils'; import { getAppropriatedPartSize } from '../Utils';
@ -34,13 +35,45 @@ const DEFAULT_CHUNK_SIZE = 64; // kb
const ONE_MB = 1024 * 1024; const ONE_MB = 1024 * 1024;
const REQUEST_TIMEOUT = 15000; const REQUEST_TIMEOUT = 15000;
class Foreman {
private deferred: Deferred | undefined;
private activeWorkers = 0;
constructor(private maxWorkers: number) {
}
requestWorker() {
this.activeWorkers++;
if (this.activeWorkers > this.maxWorkers) {
this.deferred = createDeferred();
return this.deferred.promise;
}
return Promise.resolve();
}
releaseWorker() {
this.activeWorkers--;
if (this.deferred && (this.activeWorkers <= this.maxWorkers)) {
this.deferred.resolve();
}
}
}
export async function downloadFile( export async function downloadFile(
client: TelegramClient, client: TelegramClient,
inputLocation: Api.InputFileLocation, inputLocation: Api.InputFileLocation,
fileParams: DownloadFileParams, fileParams: DownloadFileParams,
) { ) {
let { let {
partSizeKb, fileSize, workers = 1, end, partSizeKb, end,
} = fileParams;
const {
fileSize, workers = 1,
} = fileParams; } = fileParams;
const { dcId, progressCallback, start = 0 } = fileParams; const { dcId, progressCallback, start = 0 } = fileParams;
@ -88,12 +121,13 @@ export async function downloadFile(
progressCallback(progress); progressCallback(progress);
} }
// eslint-disable-next-line no-constant-condition
while (true) { while (true) {
let limit = partSize; let limit = partSize;
let isPrecise = false; let isPrecise = false;
if (Math.floor(offset / ONE_MB) !== Math.floor((offset + limit - 1) / ONE_MB)) { if (Math.floor(offset / ONE_MB) !== Math.floor((offset + limit - 1) / ONE_MB)) {
limit = ONE_MB - offset % ONE_MB; limit = ONE_MB - (offset % ONE_MB);
isPrecise = true; isPrecise = true;
} }
@ -104,6 +138,7 @@ export async function downloadFile(
break; break;
} }
// eslint-disable-next-line no-loop-func
promises.push((async () => { promises.push((async () => {
try { try {
const result = await Promise.race([ const result = await Promise.race([
@ -151,33 +186,6 @@ export async function downloadFile(
return Buffer.concat(buffers, totalLength); return Buffer.concat(buffers, totalLength);
} }
class Foreman {
private deferred: Deferred | undefined;
private activeWorkers = 0;
constructor(private maxWorkers: number) {
}
requestWorker() {
this.activeWorkers++;
if (this.activeWorkers > this.maxWorkers) {
this.deferred = createDeferred();
return this.deferred.promise;
}
return Promise.resolve();
}
releaseWorker() {
this.activeWorkers--;
if (this.deferred && (this.activeWorkers <= this.maxWorkers)) {
this.deferred.resolve();
}
}
}
function createDeferred(): Deferred { function createDeferred(): Deferred {
let resolve: Deferred['resolve']; let resolve: Deferred['resolve'];

View File

@ -1,3 +1,4 @@
// eslint-disable-next-line import/no-named-default
import { default as Api } from '../tl/api'; import { default as Api } from '../tl/api';
import TelegramClient from './TelegramClient'; import TelegramClient from './TelegramClient';
@ -61,6 +62,7 @@ export async function uploadFile(
for (let j = i; j < end; j++) { for (let j = i; j < end; j++) {
const bytes = buffer.slice(j * partSize, (j + 1) * partSize); const bytes = buffer.slice(j * partSize, (j + 1) * partSize);
// eslint-disable-next-line no-loop-func
sendingParts.push((async () => { sendingParts.push((async () => {
await sender.send( await sender.send(
isLarge isLarge
@ -94,6 +96,7 @@ export async function uploadFile(
]); ]);
} catch (err) { } catch (err) {
if (err.message === 'TIMEOUT') { if (err.message === 'TIMEOUT') {
// eslint-disable-next-line no-console
console.warn('Upload timeout. Retrying...'); console.warn('Upload timeout. Retrying...');
i -= workers; i -= workers;
continue; continue;
@ -117,10 +120,6 @@ export async function uploadFile(
}); });
} }
function generateRandomBigInt() {
return readBigIntFromBuffer(generateRandomBytes(8), false);
}
function fileToBuffer(file: File) { function fileToBuffer(file: File) {
return new Response(file).arrayBuffer(); return new Response(file).arrayBuffer();
} }

View File

@ -22,7 +22,10 @@ class AuthKey {
async setKey(value) { async setKey(value) {
if (!value) { if (!value) {
this._key = this.auxHash = this.keyId = this._hash = null; this._key = undefined;
this.auxHash = undefined;
this.keyId = undefined;
this._hash = undefined;
return; return;
} }
if (value instanceof AuthKey) { if (value instanceof AuthKey) {

View File

@ -70,6 +70,7 @@ class Factorizator {
if (g.eq(pq)) { if (g.eq(pq)) {
// eslint-disable-next-line no-constant-condition
while (true) { while (true) {
ys = (modExp(ys, BigInt(2), pq)).add(c) ys = (modExp(ys, BigInt(2), pq)).add(c)
.remainder(pq); .remainder(pq);

View File

@ -1,10 +1,10 @@
const { IGE: aes_ige } = require('@cryptography/aes'); const { IGE: AESIGE } = require('@cryptography/aes');
const Helpers = require('../Helpers'); const Helpers = require('../Helpers');
class IGENEW { class IGENEW {
constructor(key, iv) { constructor(key, iv) {
this.ige = new aes_ige(key, iv); this.ige = new AESIGE(key, iv);
} }
/** /**

View File

@ -1,8 +1,8 @@
/* eslint-disable max-len */
const BigInt = require('big-integer'); const BigInt = require('big-integer');
const { const {
readBigIntFromBuffer, readBigIntFromBuffer,
readBufferFromBigInt, readBufferFromBigInt,
getByteArray,
sha1, sha1,
generateRandomBytes, generateRandomBytes,
modExp, modExp,

View File

@ -35,7 +35,7 @@ class CTR {
this._counter = counter; this._counter = counter;
this._remainingCounter = null; this._remainingCounter = undefined;
this._remainingCounterIndex = 16; this._remainingCounterIndex = 16;
this._aes = new AES(getWords(key)); this._aes = new AES(getWords(key));
@ -95,12 +95,16 @@ class Hash {
this.data = new Uint8Array(data); this.data = new Uint8Array(data);
} }
async digest() { async digest() {
if (this.algorithm === 'sha1') { if (this.algorithm === 'sha1') {
// eslint-disable-next-line no-restricted-globals
return Buffer.from(await self.crypto.subtle.digest('SHA-1', this.data)); return Buffer.from(await self.crypto.subtle.digest('SHA-1', this.data));
} else if (this.algorithm === 'sha256') { } else if (this.algorithm === 'sha256') {
// eslint-disable-next-line no-restricted-globals
return Buffer.from(await self.crypto.subtle.digest('SHA-256', this.data)); return Buffer.from(await self.crypto.subtle.digest('SHA-256', this.data));
} }
return undefined;
} }
} }

View File

@ -22,6 +22,7 @@ class TypeNotFoundError extends Error {
read with ID ${invalidConstructorId}. Most likely, a TLObject was trying to be read when read with ID ${invalidConstructorId}. Most likely, a TLObject was trying to be read when
it should not be read. Remaining bytes: ${remaining.length}`); it should not be read. Remaining bytes: ${remaining.length}`);
if (typeof alert !== 'undefined') { if (typeof alert !== 'undefined') {
// eslint-disable-next-line no-alert
alert(`Missing MTProto Entity: Please, make sure to add TL definition for ID ${invalidConstructorId}`); alert(`Missing MTProto Entity: Please, make sure to add TL definition for ID ${invalidConstructorId}`);
} }
this.invalidConstructorId = invalidConstructorId; this.invalidConstructorId = invalidConstructorId;
@ -47,7 +48,7 @@ class InvalidChecksumError extends Error {
*/ */
class InvalidBufferError extends Error { class InvalidBufferError extends Error {
constructor(payload) { constructor(payload) {
let code = null; let code;
if (payload.length === 4) { if (payload.length === 4) {
code = -payload.readInt32LE(0); code = -payload.readInt32LE(0);
super(`Invalid response buffer (HTTP code ${code})`); super(`Invalid response buffer (HTTP code ${code})`);
@ -100,7 +101,7 @@ class BadMessageError extends Error {
'Incorrect two lower order msg_id bits (the server expects client message msg_id ' 'Incorrect two lower order msg_id bits (the server expects client message msg_id '
+ 'to be divisible by 4).', + 'to be divisible by 4).',
19: 'Container msg_id is the same as msg_id of a previously received message ' + '(this must never happen).', 19: 'Container msg_id is the same as msg_id of a previously received message (this must never happen).',
20: 20:
'Message too old, and it cannot be verified whether the server has received a ' 'Message too old, and it cannot be verified whether the server has received a '

View File

@ -2,7 +2,7 @@
* Base class for all Remote Procedure Call errors. * Base class for all Remote Procedure Call errors.
*/ */
class RPCError extends Error { class RPCError extends Error {
constructor(message, request, code = null) { constructor(message, request, code = undefined) {
super( super(
'RPCError {0}: {1}{2}' 'RPCError {0}: {1}{2}'
.replace('{0}', code) .replace('{0}', code)

View File

@ -9,7 +9,9 @@ const {
class UserMigrateError extends InvalidDCError { class UserMigrateError extends InvalidDCError {
constructor(args) { constructor(args) {
const newDc = Number(args.capture || 0); const newDc = Number(args.capture || 0);
// eslint-disable-next-line max-len
super(`The user whose identity is being used to execute queries is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`); super(`The user whose identity is being used to execute queries is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`);
// eslint-disable-next-line max-len
this.message = `The user whose identity is being used to execute queries is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`; this.message = `The user whose identity is being used to execute queries is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`;
this.newDc = newDc; this.newDc = newDc;
} }
@ -19,7 +21,9 @@ class UserMigrateError extends InvalidDCError {
class PhoneMigrateError extends InvalidDCError { class PhoneMigrateError extends InvalidDCError {
constructor(args) { constructor(args) {
const newDc = Number(args.capture || 0); const newDc = Number(args.capture || 0);
// eslint-disable-next-line max-len
super(`The phone number a user is trying to use for authorization is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`); super(`The phone number a user is trying to use for authorization is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`);
// eslint-disable-next-line max-len
this.message = `The phone number a user is trying to use for authorization is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`; this.message = `The phone number a user is trying to use for authorization is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`;
this.newDc = newDc; this.newDc = newDc;
} }
@ -28,7 +32,9 @@ class PhoneMigrateError extends InvalidDCError {
class SlowModeWaitError extends FloodError { class SlowModeWaitError extends FloodError {
constructor(args) { constructor(args) {
const seconds = Number(args.capture || 0); const seconds = Number(args.capture || 0);
// eslint-disable-next-line max-len
super(`A wait of ${seconds} seconds is required before sending another message in this chat${RPCError._fmtRequest(args.request)}`); super(`A wait of ${seconds} seconds is required before sending another message in this chat${RPCError._fmtRequest(args.request)}`);
// eslint-disable-next-line max-len
this.message = `A wait of ${seconds} seconds is required before sending another message in this chat${RPCError._fmtRequest(args.request)}`; this.message = `A wait of ${seconds} seconds is required before sending another message in this chat${RPCError._fmtRequest(args.request)}`;
this.seconds = seconds; this.seconds = seconds;
} }
@ -47,6 +53,7 @@ class FloodTestPhoneWaitError extends FloodError {
constructor(args) { constructor(args) {
const seconds = Number(args.capture || 0); const seconds = Number(args.capture || 0);
super(`A wait of ${seconds} seconds is required in the test servers${RPCError._fmtRequest(args.request)}`); super(`A wait of ${seconds} seconds is required in the test servers${RPCError._fmtRequest(args.request)}`);
// eslint-disable-next-line max-len
this.message = `A wait of ${seconds} seconds is required in the test servers${RPCError._fmtRequest(args.request)}`; this.message = `A wait of ${seconds} seconds is required in the test servers${RPCError._fmtRequest(args.request)}`;
this.seconds = seconds; this.seconds = seconds;
} }
@ -56,6 +63,7 @@ class FileMigrateError extends InvalidDCError {
constructor(args) { constructor(args) {
const newDc = Number(args.capture || 0); const newDc = Number(args.capture || 0);
super(`The file to be accessed is currently stored in DC ${newDc}${RPCError._fmtRequest(args.request)}`); super(`The file to be accessed is currently stored in DC ${newDc}${RPCError._fmtRequest(args.request)}`);
// eslint-disable-next-line max-len
this.message = `The file to be accessed is currently stored in DC ${newDc}${RPCError._fmtRequest(args.request)}`; this.message = `The file to be accessed is currently stored in DC ${newDc}${RPCError._fmtRequest(args.request)}`;
this.newDc = newDc; this.newDc = newDc;
} }
@ -74,6 +82,7 @@ class EmailUnconfirmedError extends BadRequestError {
constructor(args) { constructor(args) {
const codeLength = Number(args.capture || 0); const codeLength = Number(args.capture || 0);
super(`Email unconfirmed, the length of the code must be ${codeLength}${RPCError._fmtRequest(args.request)}`); super(`Email unconfirmed, the length of the code must be ${codeLength}${RPCError._fmtRequest(args.request)}`);
// eslint-disable-next-line max-len
this.message = `Email unconfirmed, the length of the code must be ${codeLength}${RPCError._fmtRequest(args.request)}`; this.message = `Email unconfirmed, the length of the code must be ${codeLength}${RPCError._fmtRequest(args.request)}`;
this.codeLength = codeLength; this.codeLength = codeLength;
} }

View File

@ -11,7 +11,7 @@ function RPCMessageToError(rpcError, request) {
for (const [msgRegex, Cls] of rpcErrorRe) { for (const [msgRegex, Cls] of rpcErrorRe) {
const m = rpcError.errorMessage.match(msgRegex); const m = rpcError.errorMessage.match(msgRegex);
if (m) { if (m) {
const capture = m.length === 2 ? parseInt(m[1]) : null; const capture = m.length === 2 ? parseInt(m[1], 10) : undefined;
return new Cls({ return new Cls({
request, request,
capture, capture,
@ -22,9 +22,13 @@ function RPCMessageToError(rpcError, request) {
return new RPCError(rpcError.errorMessage, request); return new RPCError(rpcError.errorMessage, request);
} }
const Common = require('./Common');
const RPCBaseErrors = require('./RPCBaseErrors');
const RPCErrorList = require('./RPCErrorList');
module.exports = { module.exports = {
RPCMessageToError, RPCMessageToError,
...require('./Common'), ...Common,
...require('./RPCBaseErrors'), ...RPCBaseErrors,
...require('./RPCErrorList'), ...RPCErrorList,
}; };

View File

@ -2,8 +2,8 @@ const { EventBuilder } = require('./common');
class Raw extends EventBuilder { class Raw extends EventBuilder {
constructor(args = { constructor(args = {
types: null, types: undefined,
func: null, func: undefined,
}) { }) {
super(); super();
if (!args.types) { if (!args.types) {
@ -13,7 +13,7 @@ class Raw extends EventBuilder {
} }
} }
build(update, others = null) { build(update) {
return update; return update;
} }
} }

View File

@ -1,8 +1,8 @@
class EventBuilder { class EventBuilder {
constructor(args = { constructor(args = {
chats: null, chats: undefined,
blacklistChats: null, blacklistChats: undefined,
func: null, func: undefined,
}) { }) {
this.chats = args.chats; this.chats = args.chats;
this.blacklistChats = Boolean(args.blacklistChats); this.blacklistChats = Boolean(args.blacklistChats);
@ -10,17 +10,13 @@ class EventBuilder {
this.func = args.func; this.func = args.func;
} }
build(update, others = null) { // eslint-disable-next-line @typescript-eslint/no-unused-vars
build(update) {
} }
} }
class EventCommon {
}
module.exports = { module.exports = {
EventBuilder, EventBuilder,
EventCommon,
}; };

View File

@ -10,7 +10,7 @@ class BinaryReader {
*/ */
constructor(data) { constructor(data) {
this.stream = data; this.stream = data;
this._last = null; this._last = undefined;
this.offset = 0; this.offset = 0;
} }
@ -234,7 +234,7 @@ class BinaryReader {
* Closes the reader. * Closes the reader.
*/ */
close() { close() {
this.stream = null; this.stream = undefined;
} }
// region Position related // region Position related

View File

@ -1,4 +1,4 @@
let _level = null; let _level;
class Logger { class Logger {
static levels = ['error', 'warn', 'info', 'debug']; static levels = ['error', 'warn', 'info', 'debug'];
@ -92,12 +92,12 @@ class Logger {
} }
if (this.canSend(level)) { if (this.canSend(level)) {
if (!this.isBrowser) { if (!this.isBrowser) {
// eslint-disable-next-line no-console
console.log(color + this.format(message, level) + this.colors.end); console.log(color + this.format(message, level) + this.colors.end);
} else { } else {
// eslint-disable-next-line no-console
console.log(this.colors.start + this.format(message, level), color); console.log(this.colors.start + this.format(message, level), color);
} }
} else {
} }
} }
} }

View File

@ -49,7 +49,7 @@ class MessagePacker {
} }
if (!this._queue[this._queue.length - 1]) { if (!this._queue[this._queue.length - 1]) {
this._queue = []; this._queue = [];
return; return undefined;
} }
let data; let data;
let buffer = new BinaryWriter(Buffer.alloc(0)); let buffer = new BinaryWriter(Buffer.alloc(0));
@ -69,7 +69,8 @@ class MessagePacker {
buffer, state.data, state.request.classType === 'request', buffer, state.data, state.request.classType === 'request',
afterId, afterId,
); );
this._log.debug(`Assigned msgId = ${state.msgId} to ${state.request.className || state.request.constructor.name}`); this._log.debug(`Assigned msgId = ${state.msgId} to ${state.request.className
|| state.request.constructor.name}`);
batch.push(state); batch.push(state);
continue; continue;
} }
@ -77,12 +78,13 @@ class MessagePacker {
this._queue.unshift(state); this._queue.unshift(state);
break; break;
} }
this._log.warn(`Message payload for ${state.request.className || state.request.constructor.name} is too long ${state.data.length} and cannot be sent`); this._log.warn(`Message payload for ${state.request.className
|| state.request.constructor.name} is too long ${state.data.length} and cannot be sent`);
state.reject('Request Payload is too big'); state.reject('Request Payload is too big');
size = 0; size = 0;
} }
if (!batch.length) { if (!batch.length) {
return null; return undefined;
} }
if (batch.length > 1) { if (batch.length > 1) {
const b = Buffer.alloc(8); const b = Buffer.alloc(8);

View File

@ -15,12 +15,13 @@ class PromisedWebSockets {
process.__nwjs process.__nwjs
*/ */
this.client = null; this.client = undefined;
this.closed = true; this.closed = true;
} }
async readExactly(number) { async readExactly(number) {
let readData = Buffer.alloc(0); let readData = Buffer.alloc(0);
// eslint-disable-next-line no-constant-condition
while (true) { while (true) {
const thisTime = await this.read(number); const thisTime = await this.read(number);
readData = Buffer.concat([readData, thisTime]); readData = Buffer.concat([readData, thisTime]);
@ -71,7 +72,7 @@ class PromisedWebSockets {
} }
} }
async connect(port, ip) { connect(port, ip) {
this.stream = Buffer.alloc(0); this.stream = Buffer.alloc(0);
this.canRead = new Promise((resolve) => { this.canRead = new Promise((resolve) => {
this.resolveRead = resolve; this.resolveRead = resolve;
@ -93,6 +94,7 @@ class PromisedWebSockets {
}; };
// CONTEST // CONTEST
// Seems to not be working, at least in a web worker // Seems to not be working, at least in a web worker
// eslint-disable-next-line no-restricted-globals
self.addEventListener('offline', async () => { self.addEventListener('offline', async () => {
await this.close(); await this.close();
this.resolveRead(false); this.resolveRead(false);
@ -112,7 +114,7 @@ class PromisedWebSockets {
this.closed = true; this.closed = true;
} }
async receive() { receive() {
this.client.onmessage = async (message) => { this.client.onmessage = async (message) => {
const release = await mutex.acquire(); const release = await mutex.acquire();
try { try {

View File

@ -58,16 +58,16 @@ async function doAuthentication(sender, log) {
}); });
// sha_digest + data + random_bytes // sha_digest + data + random_bytes
let cipherText = null; let cipherText;
let targetFingerprint = null; let targetFingerprint;
for (const fingerprint of resPQ.serverPublicKeyFingerprints) { for (const fingerprint of resPQ.serverPublicKeyFingerprints) {
cipherText = await RSA.encrypt(fingerprint.toString(), pqInnerData.getBytes()); cipherText = await RSA.encrypt(fingerprint.toString(), pqInnerData.getBytes());
if (cipherText !== null && cipherText !== undefined) { if (cipherText !== undefined) {
targetFingerprint = fingerprint; targetFingerprint = fingerprint;
break; break;
} }
} }
if (cipherText === null || cipherText === undefined) { if (cipherText === undefined) {
throw new SecurityError('Step 2 could not find a valid key for fingerprints'); throw new SecurityError('Step 2 could not find a valid key for fingerprints');
} }
@ -81,7 +81,8 @@ async function doAuthentication(sender, log) {
encryptedData: cipherText, encryptedData: cipherText,
}), }),
); );
if (!(serverDhParams instanceof constructors.ServerDHParamsOk || serverDhParams instanceof constructors.ServerDHParamsFail)) { if (!(serverDhParams instanceof constructors.ServerDHParamsOk
|| serverDhParams instanceof constructors.ServerDHParamsFail)) {
throw new Error(`Step 2.1 answer was ${serverDhParams}`); throw new Error(`Step 2.1 answer was ${serverDhParams}`);
} }
if (serverDhParams.nonce.neq(resPQ.nonce)) { if (serverDhParams.nonce.neq(resPQ.nonce)) {

View File

@ -3,7 +3,6 @@
* in plain text, when no authorization key has been created yet. * in plain text, when no authorization key has been created yet.
*/ */
const BigInt = require('big-integer'); const BigInt = require('big-integer');
const Helpers = require('../Helpers');
const MTProtoState = require('./MTProtoState'); const MTProtoState = require('./MTProtoState');
const BinaryReader = require('../extensions/BinaryReader'); const BinaryReader = require('../extensions/BinaryReader');
const { InvalidBufferError } = require('../errors/Common'); const { InvalidBufferError } = require('../errors/Common');

View File

@ -50,16 +50,16 @@ const { TypeNotFoundError } = require('../errors/Common');
*/ */
class MTProtoSender { class MTProtoSender {
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
logger: null, logger: undefined,
retries: Infinity, retries: Infinity,
delay: 2000, delay: 2000,
autoReconnect: true, autoReconnect: true,
connectTimeout: null, connectTimeout: undefined,
authKeyCallback: null, authKeyCallback: undefined,
updateCallback: null, updateCallback: undefined,
autoReconnectCallback: null, autoReconnectCallback: undefined,
isMainSender: null, isMainSender: undefined,
onConnectionBreak: null, onConnectionBreak: undefined,
}; };
/** /**
@ -68,7 +68,7 @@ class MTProtoSender {
*/ */
constructor(authKey, opts) { constructor(authKey, opts) {
const args = { ...MTProtoSender.DEFAULT_OPTIONS, ...opts }; const args = { ...MTProtoSender.DEFAULT_OPTIONS, ...opts };
this._connection = null; this._connection = undefined;
this._log = args.logger; this._log = args.logger;
this._dcId = args.dcId; this._dcId = args.dcId;
this._retries = args.retries; this._retries = args.retries;
@ -96,8 +96,8 @@ class MTProtoSender {
/** /**
* We need to join the loops upon disconnection * We need to join the loops upon disconnection
*/ */
this._send_loop_handle = null; this._send_loop_handle = undefined;
this._recv_loop_handle = null; this._recv_loop_handle = undefined;
/** /**
* Preserving the references of the AuthKey and state is important * Preserving the references of the AuthKey and state is important
@ -180,6 +180,7 @@ class MTProtoSender {
await Helpers.sleep(this._delay); await Helpers.sleep(this._delay);
} }
} }
return true;
} }
isConnected() { isConnected() {
@ -286,10 +287,10 @@ class MTProtoSender {
this._log.info('Connection to %s complete!'.replace('%s', this._connection.toString())); this._log.info('Connection to %s complete!'.replace('%s', this._connection.toString()));
} }
async _disconnect(error = null) { async _disconnect() {
this._send_queue.rejectAll(); this._send_queue.rejectAll();
if (this._connection === null) { if (this._connection === undefined) {
this._log.info('Not disconnecting (already have no connection)'); this._log.info('Not disconnecting (already have no connection)');
return; return;
} }
@ -495,12 +496,12 @@ class MTProtoSender {
* @private * @private
*/ */
_handleRPCResult(message) { _handleRPCResult(message) {
const RPCResult = message.obj; const result = message.obj;
const state = this._pending_state[RPCResult.reqMsgId]; const state = this._pending_state[result.reqMsgId];
if (state) { if (state) {
delete this._pending_state[RPCResult.reqMsgId]; delete this._pending_state[result.reqMsgId];
} }
this._log.debug(`Handling RPC result for message ${RPCResult.reqMsgId}`); this._log.debug(`Handling RPC result for message ${result.reqMsgId}`);
if (!state) { if (!state) {
// TODO We should not get responses to things we never sent // TODO We should not get responses to things we never sent
@ -508,27 +509,27 @@ class MTProtoSender {
// See #658, #759 and #958. They seem to happen in a container // See #658, #759 and #958. They seem to happen in a container
// which contain the real response right after. // which contain the real response right after.
try { try {
const reader = new BinaryReader(RPCResult.body); const reader = new BinaryReader(result.body);
if (!(reader.tgReadObject() instanceof upload.File)) { if (!(reader.tgReadObject() instanceof upload.File)) {
throw new TypeNotFoundError('Not an upload.File'); throw new TypeNotFoundError('Not an upload.File');
} }
} catch (e) { } catch (e) {
this._log.error(e); this._log.error(e);
if (e instanceof TypeNotFoundError) { if (e instanceof TypeNotFoundError) {
this._log.info(`Received response without parent request: ${RPCResult.body}`); this._log.info(`Received response without parent request: ${result.body}`);
return; return;
} else { } else {
throw e; throw e;
} }
} }
} }
if (RPCResult.error) { if (result.error) {
// eslint-disable-next-line new-cap // eslint-disable-next-line new-cap
const error = RPCMessageToError(RPCResult.error, state.request); const error = RPCMessageToError(result.error, state.request);
this._send_queue.append(new RequestState(new MsgsAck({ msgIds: [state.msgId] }))); this._send_queue.append(new RequestState(new MsgsAck({ msgIds: [state.msgId] })));
state.reject(error); state.reject(error);
} else { } else {
const reader = new BinaryReader(RPCResult.body); const reader = new BinaryReader(result.body);
const read = state.request.readResult(reader); const read = state.request.readResult(reader);
state.resolve(read); state.resolve(read);
} }
@ -562,7 +563,7 @@ class MTProtoSender {
await this._processMessage(message); await this._processMessage(message);
} }
async _handleUpdate(message) { _handleUpdate(message) {
if (message.obj.SUBCLASS_OF_ID !== 0x8af52aac) { if (message.obj.SUBCLASS_OF_ID !== 0x8af52aac) {
// crc32(b'Updates') // crc32(b'Updates')
this._log.warn(`Note: ${message.obj.className} is not an update, not dispatching it`); this._log.warn(`Note: ${message.obj.className} is not an update, not dispatching it`);
@ -582,7 +583,7 @@ class MTProtoSender {
* @returns {Promise<void>} * @returns {Promise<void>}
* @private * @private
*/ */
async _handlePong(message) { _handlePong(message) {
const pong = message.obj; const pong = message.obj;
this._log.debug(`Handling pong for message ${pong.msgId}`); this._log.debug(`Handling pong for message ${pong.msgId}`);
const state = this._pending_state[pong.msgId]; const state = this._pending_state[pong.msgId];
@ -603,7 +604,7 @@ class MTProtoSender {
* @returns {Promise<void>} * @returns {Promise<void>}
* @private * @private
*/ */
async _handleBadServerSalt(message) { _handleBadServerSalt(message) {
const badSalt = message.obj; const badSalt = message.obj;
this._log.debug(`Handling bad salt for message ${badSalt.badMsgId}`); this._log.debug(`Handling bad salt for message ${badSalt.badMsgId}`);
this._state.salt = badSalt.newServerSalt; this._state.salt = badSalt.newServerSalt;
@ -621,7 +622,7 @@ class MTProtoSender {
* @returns {Promise<void>} * @returns {Promise<void>}
* @private * @private
*/ */
async _handleBadNotification(message) { _handleBadNotification(message) {
const badMsg = message.obj; const badMsg = message.obj;
const states = this._popStates(badMsg.badMsgId); const states = this._popStates(badMsg.badMsgId);
this._log.debug(`Handling bad msg ${JSON.stringify(badMsg)}`); this._log.debug(`Handling bad msg ${JSON.stringify(badMsg)}`);
@ -657,7 +658,7 @@ class MTProtoSender {
* @returns {Promise<void>} * @returns {Promise<void>}
* @private * @private
*/ */
async _handleDetailedInfo(message) { _handleDetailedInfo(message) {
// TODO https://goo.gl/VvpCC6 // TODO https://goo.gl/VvpCC6
const msgId = message.obj.answerMsgId; const msgId = message.obj.answerMsgId;
this._log.debug(`Handling detailed info for message ${msgId}`); this._log.debug(`Handling detailed info for message ${msgId}`);
@ -672,7 +673,7 @@ class MTProtoSender {
* @returns {Promise<void>} * @returns {Promise<void>}
* @private * @private
*/ */
async _handleNewDetailedInfo(message) { _handleNewDetailedInfo(message) {
// TODO https://goo.gl/VvpCC6 // TODO https://goo.gl/VvpCC6
const msgId = message.obj.answerMsgId; const msgId = message.obj.answerMsgId;
this._log.debug(`Handling new detailed info for message ${msgId}`); this._log.debug(`Handling new detailed info for message ${msgId}`);
@ -687,7 +688,7 @@ class MTProtoSender {
* @returns {Promise<void>} * @returns {Promise<void>}
* @private * @private
*/ */
async _handleNewSessionCreated(message) { _handleNewSessionCreated(message) {
// TODO https://goo.gl/LMyN7A // TODO https://goo.gl/LMyN7A
this._log.debug('Handling new session created'); this._log.debug('Handling new session created');
this._state.salt = message.obj.serverSalt; this._state.salt = message.obj.serverSalt;
@ -711,7 +712,7 @@ class MTProtoSender {
* @returns {Promise<void>} * @returns {Promise<void>}
* @private * @private
*/ */
async _handleAck(message) { _handleAck(message) {
const ack = message.obj; const ack = message.obj;
this._log.debug(`Handling acknowledge for ${ack.msgIds}`); this._log.debug(`Handling acknowledge for ${ack.msgIds}`);
for (const msgId of ack.msgIds) { for (const msgId of ack.msgIds) {
@ -732,7 +733,7 @@ class MTProtoSender {
* @returns {Promise<void>} * @returns {Promise<void>}
* @private * @private
*/ */
async _handleFutureSalts(message) { _handleFutureSalts(message) {
// TODO save these salts and automatically adjust to the // TODO save these salts and automatically adjust to the
// correct one whenever the salt in use expires. // correct one whenever the salt in use expires.
this._log.debug(`Handling future salts for message ${message.msgId}`); this._log.debug(`Handling future salts for message ${message.msgId}`);
@ -751,7 +752,7 @@ class MTProtoSender {
* @returns {Promise<void>} * @returns {Promise<void>}
* @private * @private
*/ */
async _handleStateForgotten(message) { _handleStateForgotten(message) {
this._send_queue.append( this._send_queue.append(
new RequestState(new MsgsStateInfo(message.msgId, String.fromCharCode(1) new RequestState(new MsgsStateInfo(message.msgId, String.fromCharCode(1)
.repeat(message.obj.msgIds))), .repeat(message.obj.msgIds))),
@ -760,14 +761,17 @@ class MTProtoSender {
/** /**
* Handles :tl:`MsgsAllInfo` by doing nothing (yet). * Handles :tl:`MsgsAllInfo` by doing nothing (yet).
* used as part of the telegram protocol https://core.telegram.org/mtproto/service_messages_about_messages
* This message does not require an acknowledgment.
* @param message * @param message
* @returns {Promise<void>} * @returns {Promise<void>}
* @private * @private
*/ */
async _handleMsgAll(message) { // eslint-disable-next-line @typescript-eslint/no-unused-vars
_handleMsgAll(message) {
} }
async reconnect() { reconnect() {
if (this._user_connected && !this._reconnecting) { if (this._user_connected && !this._reconnecting) {
this._reconnecting = true; this._reconnecting = true;
// TODO Should we set this? // TODO Should we set this?
@ -785,7 +789,7 @@ class MTProtoSender {
this._log.warn(err); this._log.warn(err);
} }
this._send_queue.append(null); this._send_queue.append(undefined);
this._state.reset(); this._state.reset();
await this.connect(this._connection, true); await this.connect(this._connection, true);

View File

@ -1,3 +1,5 @@
const BigInt = require('big-integer');
const Helpers = require('../Helpers'); const Helpers = require('../Helpers');
const IGE = require('../crypto/IGE'); const IGE = require('../crypto/IGE');
const BinaryReader = require('../extensions/BinaryReader'); const BinaryReader = require('../extensions/BinaryReader');
@ -8,12 +10,9 @@ const {
InvalidBufferError, InvalidBufferError,
} = require('../errors/Common'); } = require('../errors/Common');
const { InvokeAfterMsg } = require('../tl').requests; const { InvokeAfterMsg } = require('../tl').requests;
const BigInt = require('big-integer');
const { const {
toSignedLittleBuffer, toSignedLittleBuffer,
readBufferFromBigInt,
} = require('../Helpers'); } = require('../Helpers');
const { readBigIntFromBuffer } = require('../Helpers');
class MTProtoState { class MTProtoState {
/** /**
@ -47,7 +46,9 @@ class MTProtoState {
this.timeOffset = 0; this.timeOffset = 0;
this.salt = 0; this.salt = 0;
this.id = this._sequence = this._lastMsgId = null; this.id = undefined;
this._sequence = undefined;
this._lastMsgId = undefined;
this.reset(); this.reset();
} }

View File

@ -1,11 +1,11 @@
class RequestState { class RequestState {
constructor(request, after = null) { constructor(request, after = undefined) {
this.containerId = null; this.containerId = undefined;
this.msgId = null; this.msgId = undefined;
this.request = request; this.request = request;
this.data = request.getBytes(); this.data = request.getBytes();
this.after = after; this.after = after;
this.result = null; this.result = undefined;
this.promise = new Promise((resolve, reject) => { this.promise = new Promise((resolve, reject) => {
this.resolve = resolve; this.resolve = resolve;
this.reject = reject; this.reject = reject;

View File

@ -13,7 +13,7 @@ const AsyncQueue = require('../../extensions/AsyncQueue');
* the client is disconnected (includes remote disconnections). * the client is disconnected (includes remote disconnections).
*/ */
class Connection { class Connection {
PacketCodecClass = null; PacketCodecClass = undefined;
constructor(ip, port, dcId, loggers) { constructor(ip, port, dcId, loggers) {
this._ip = ip; this._ip = ip;
@ -21,10 +21,10 @@ class Connection {
this._dcId = dcId; this._dcId = dcId;
this._log = loggers; this._log = loggers;
this._connected = false; this._connected = false;
this._sendTask = null; this._sendTask = undefined;
this._recvTask = null; this._recvTask = undefined;
this._codec = null; this._codec = undefined;
this._obfuscation = null; // TcpObfuscated and MTProxy this._obfuscation = undefined; // TcpObfuscated and MTProxy
this._sendArray = new AsyncQueue(); this._sendArray = new AsyncQueue();
this._recvArray = new AsyncQueue(); this._recvArray = new AsyncQueue();
// this.socket = new PromiseSocket(new Socket()) // this.socket = new PromiseSocket(new Socket())
@ -53,7 +53,7 @@ class Connection {
async disconnect() { async disconnect() {
this._connected = false; this._connected = false;
await this._recvArray.push(null); await this._recvArray.push(undefined);
await this.socket.close(); await this.socket.close();
} }
@ -81,7 +81,7 @@ class Connection {
while (this._connected) { while (this._connected) {
const data = await this._sendArray.pop(); const data = await this._sendArray.pop();
if (!data) { if (!data) {
this._sendTask = null; this._sendTask = undefined;
return; return;
} }
await this._send(data); await this._send(data);
@ -116,13 +116,13 @@ class Connection {
} }
} }
async _send(data) { _send(data) {
const encodedPacket = this._codec.encodePacket(data); const encodedPacket = this._codec.encodePacket(data);
this.socket.write(encodedPacket); this.socket.write(encodedPacket);
} }
async _recv() { _recv() {
return await this._codec.readPacket(this.socket); return this._codec.readPacket(this.socket);
} }
toString() { toString() {
@ -131,9 +131,9 @@ class Connection {
} }
class ObfuscatedConnection extends Connection { class ObfuscatedConnection extends Connection {
ObfuscatedIO = null; ObfuscatedIO = undefined;
async _initConn() { _initConn() {
this._obfuscation = new this.ObfuscatedIO(this); this._obfuscation = new this.ObfuscatedIO(this);
this.socket.write(this._obfuscation.header); this.socket.write(this._obfuscation.header);
} }
@ -143,8 +143,8 @@ class ObfuscatedConnection extends Connection {
} }
async _recv() { _recv() {
return await this._codec.readPacket(this._obfuscation); return this._codec.readPacket(this._obfuscation);
} }
} }
@ -153,13 +153,15 @@ class PacketCodec {
this._conn = connection; this._conn = connection;
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
encodePacket(data) { encodePacket(data) {
throw new Error('Not Implemented'); throw new Error('Not Implemented');
// Override // Override
} }
async readPacket(reader) { // eslint-disable-next-line @typescript-eslint/no-unused-vars
readPacket(reader) {
// override // override
throw new Error('Not Implemented'); throw new Error('Not Implemented');
} }

View File

@ -36,7 +36,7 @@ class AbridgedPacketCodec extends PacketCodec {
.readInt32LE(0); .readInt32LE(0);
} }
return await reader.read(length << 2); return reader.read(length << 2);
} }
} }

View File

@ -4,7 +4,7 @@ const { AbridgedPacketCodec } = require('./TCPAbridged');
const CTR = require('../../crypto/CTR'); const CTR = require('../../crypto/CTR');
class ObfuscatedIO { class ObfuscatedIO {
header = null; header = undefined;
constructor(connection) { constructor(connection) {
this.connection = connection.socket; this.connection = connection.socket;

View File

@ -1,8 +1,4 @@
class Session { class Session {
constructor() {
}
/** /**
* Creates a clone of this session file * Creates a clone of this session file
* @param toInstance {Session|null} * @param toInstance {Session|null}
@ -59,6 +55,7 @@ class Session {
* @param serverAddress {string} * @param serverAddress {string}
* @param port {number} * @param port {number}
*/ */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
setDC(dcId, serverAddress, port) { setDC(dcId, serverAddress, port) {
throw new Error('Not implemented'); throw new Error('Not implemented');
} }

View File

@ -1,3 +1,4 @@
/* eslint-disable no-restricted-globals */
const StorageSession = require('./StorageSession'); const StorageSession = require('./StorageSession');
const CACHE_NAME = 'GramJs'; const CACHE_NAME = 'GramJs';
@ -13,7 +14,7 @@ class CacheApiSession extends StorageSession {
const request = new Request(this._storageKey); const request = new Request(this._storageKey);
const cache = await self.caches.open(CACHE_NAME); const cache = await self.caches.open(CACHE_NAME);
const cached = await cache.match(request); const cached = await cache.match(request);
return cached ? cached.text() : null; return cached ? cached.text() : undefined;
} }
async _saveToCache(data) { async _saveToCache(data) {

View File

@ -4,15 +4,15 @@ const StorageSession = require('./StorageSession');
const CACHE_NAME = 'GramJs'; const CACHE_NAME = 'GramJs';
class IdbSession extends StorageSession { class IdbSession extends StorageSession {
async _delete() { _delete() {
return idb.del(`${CACHE_NAME}:${this._storageKey}`); return idb.del(`${CACHE_NAME}:${this._storageKey}`);
} }
async _fetchFromCache() { _fetchFromCache() {
return idb.get(`${CACHE_NAME}:${this._storageKey}`); return idb.get(`${CACHE_NAME}:${this._storageKey}`);
} }
async _saveToCache(data) { _saveToCache(data) {
return idb.set(`${CACHE_NAME}:${this._storageKey}`, data); return idb.set(`${CACHE_NAME}:${this._storageKey}`, data);
} }
} }

View File

@ -1,15 +1,15 @@
const StorageSession = require('./StorageSession'); const StorageSession = require('./StorageSession');
class LocalStorageSession extends StorageSession { class LocalStorageSession extends StorageSession {
async _delete() { _delete() {
return localStorage.removeItem(this._storageKey); return localStorage.removeItem(this._storageKey);
} }
async _fetchFromCache(key) { _fetchFromCache() {
return localStorage.getItem(this._storageKey); return localStorage.getItem(this._storageKey);
} }
async _saveToCache(key, data) { _saveToCache(data) {
return localStorage.setItem(this._storageKey, data); return localStorage.setItem(this._storageKey, data);
} }
} }

View File

@ -1,15 +1,13 @@
const utils = require('../Utils');
const types = require('../tl').constructors;
const Session = require('./Abstract'); const Session = require('./Abstract');
class MemorySession extends Session { class MemorySession extends Session {
constructor() { constructor() {
super(); super();
this._serverAddress = null; this._serverAddress = undefined;
this._dcId = 0; this._dcId = 0;
this._port = null; this._port = undefined;
this._takeoutId = null; this._takeoutId = undefined;
this._entities = new Set(); this._entities = new Set();
this._updateStates = {}; this._updateStates = {};

View File

@ -48,7 +48,9 @@ class StorageSession extends MemorySession {
} }
}); });
} catch (err) { } catch (err) {
// eslint-disable-next-line no-console
console.warn('Failed to retrieve or parse session from storage'); console.warn('Failed to retrieve or parse session from storage');
// eslint-disable-next-line no-console
console.warn(err); console.warn(err);
} }
} }
@ -101,12 +103,15 @@ class StorageSession extends MemorySession {
const authKey = this._authKeys[dcId]; const authKey = this._authKeys[dcId];
sessionData.keys[dcId] = authKey._key; sessionData.keys[dcId] = authKey._key;
sessionData.hashes[dcId] = authKey._hash; sessionData.hashes[dcId] = authKey._hash;
return undefined;
}); });
try { try {
await this._saveToCache(JSON.stringify(sessionData)); await this._saveToCache(JSON.stringify(sessionData));
} catch (err) { } catch (err) {
// eslint-disable-next-line no-console
console.warn('Failed to update session in storage'); console.warn('Failed to update session in storage');
// eslint-disable-next-line no-console
console.warn(err); console.warn(err);
} }
} }
@ -115,23 +120,27 @@ class StorageSession extends MemorySession {
try { try {
return await this._delete(); return await this._delete();
} catch (err) { } catch (err) {
// eslint-disable-next-line no-console
console.warn('Failed to delete session from storage'); console.warn('Failed to delete session from storage');
// eslint-disable-next-line no-console
console.warn(err); console.warn(err);
} }
return undefined;
} }
// @abstract // @abstract
async _delete() { _delete() {
throw new Error('Not Implemented'); throw new Error('Not Implemented');
} }
// @abstract // @abstract
async _fetchFromCache() { _fetchFromCache() {
throw new Error('Not Implemented'); throw new Error('Not Implemented');
} }
// @abstract // @abstract
async _saveToCache(data) { // eslint-disable-next-line @typescript-eslint/no-unused-vars
_saveToCache(data) {
throw new Error('Not Implemented'); throw new Error('Not Implemented');
} }
} }

View File

@ -21,7 +21,7 @@ class StringSession extends MemorySession {
* `decode` definition must be ``function decode(value: string) -> Buffer:``. * `decode` definition must be ``function decode(value: string) -> Buffer:``.
* @param session {string|null} * @param session {string|null}
*/ */
constructor(session = null) { constructor(session = undefined) {
super(); super();
if (session) { if (session) {
if (session[0] !== CURRENT_VERSION) { if (session[0] !== CURRENT_VERSION) {
@ -96,7 +96,7 @@ class StringSession extends MemorySession {
setAuthKey(authKey, dcId) { setAuthKey(authKey, dcId) {
if (dcId && dcId !== this.dcId) { if (dcId && dcId !== this.dcId) {
// Not supported. // Not supported.
return undefined; return;
} }
this.authKey = authKey; this.authKey = authKey;

View File

@ -34,10 +34,14 @@ class MTProtoRequest {
throw Error(`Not overload ${this.constructor.name}`); throw Error(`Not overload ${this.constructor.name}`);
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
onResponse(buffer) { onResponse(buffer) {
throw Error(`Not overload ${this.constructor.name}`);
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars
onException(exception) { onException(exception) {
throw Error(`Not overload ${this.constructor.name}`);
} }
} }

View File

@ -4,7 +4,6 @@ const {
serializeDate, serializeDate,
} = require('./generationHelpers'); } = require('./generationHelpers');
const { const {
readBufferFromBigInt,
toSignedLittleBuffer, toSignedLittleBuffer,
} = require('../Helpers'); } = require('../Helpers');
@ -32,6 +31,7 @@ const AUTO_CASTS = new Set([
]) ])
*/ */
// eslint-disable-next-line no-restricted-globals
const CACHING_SUPPORTED = typeof self !== 'undefined' && self.localStorage !== undefined; const CACHING_SUPPORTED = typeof self !== 'undefined' && self.localStorage !== undefined;
const CACHE_KEY = 'GramJs:apiCache'; const CACHE_KEY = 'GramJs:apiCache';
@ -93,27 +93,33 @@ function extractParams(fileContent) {
const constructors = []; const constructors = [];
const functions = []; const functions = [];
for (const d of f) { for (const d of f) {
d.isFunction ? functions.push(d) : constructors.push(d); if (d.isFunction) {
functions.push(d);
} else {
constructors.push(d);
}
} }
return [constructors, functions]; return [constructors, functions];
} }
function argToBytes(x, type) { function argToBytes(x, type) {
switch (type) { switch (type) {
case 'int': case 'int': {
const i = Buffer.alloc(4); const i = Buffer.alloc(4);
i.writeInt32LE(x, 0); i.writeInt32LE(x, 0);
return i; return i;
}
case 'long': case 'long':
return toSignedLittleBuffer(x, 8); return toSignedLittleBuffer(x, 8);
case 'int128': case 'int128':
return toSignedLittleBuffer(x, 16); return toSignedLittleBuffer(x, 16);
case 'int256': case 'int256':
return toSignedLittleBuffer(x, 32); return toSignedLittleBuffer(x, 32);
case 'double': case 'double': {
const d = Buffer.alloc(8); const d = Buffer.alloc(8);
d.writeDoubleLE(x, 0); d.writeDoubleLE(x, 0);
return d; return d;
}
case 'string': case 'string':
return serializeBytes(x); return serializeBytes(x);
case 'Bool': case 'Bool':
@ -201,7 +207,7 @@ function getArgFromReader(reader, arg) {
if (!arg.skipConstructorId) { if (!arg.skipConstructorId) {
return reader.tgReadObject(); return reader.tgReadObject();
} else { } else {
return api.constructors[arg.type].fromReader(reader); throw new Error(`Unknown type ${arg}`);
} }
} }
} }
@ -254,13 +260,13 @@ function createClasses(classesType, params) {
const arg = argsConfig[argName]; const arg = argsConfig[argName];
if (arg.isFlag) { if (arg.isFlag) {
if (arg.type === 'true') { if (arg.type === 'true') {
args[argName] = Boolean(args.flags & 1 << arg.flagIndex); args[argName] = Boolean(args.flags & (1 << arg.flagIndex));
continue; continue;
} }
if (args.flags & 1 << arg.flagIndex) { if (args.flags & (1 << arg.flagIndex)) {
args[argName] = getArgFromReader(reader, arg); args[argName] = getArgFromReader(reader, arg);
} else { } else {
args[argName] = null; args[argName] = undefined;
} }
} else { } else {
if (arg.flagIndicator) { if (arg.flagIndicator) {
@ -282,7 +288,8 @@ function createClasses(classesType, params) {
for (const arg in argsConfig) { for (const arg in argsConfig) {
if (argsConfig.hasOwnProperty(arg)) { if (argsConfig.hasOwnProperty(arg)) {
if (argsConfig[arg].isFlag) { if (argsConfig[arg].isFlag) {
if ((this[arg] === false && argsConfig[arg].type === 'true') || this[arg] === null || this[arg] === undefined) { if ((this[arg] === false && argsConfig[arg].type === 'true')
|| this[arg] === undefined) {
continue; continue;
} }
} }
@ -301,7 +308,8 @@ function createClasses(classesType, params) {
let flagCalculate = 0; let flagCalculate = 0;
for (const f in argsConfig) { for (const f in argsConfig) {
if (argsConfig[f].isFlag) { if (argsConfig[f].isFlag) {
if ((this[f] === false && argsConfig[f].type === 'true') || this[f] === undefined || this[f] === null) { if ((this[f] === false && argsConfig[f].type === 'true')
|| this[f] === undefined) {
flagCalculate |= 0; flagCalculate |= 0;
} else { } else {
flagCalculate |= 1 << argsConfig[f].flagIndex; flagCalculate |= 1 << argsConfig[f].flagIndex;

View File

@ -34,12 +34,12 @@ class GZIPPacked {
return Buffer.from(inflate(input)); return Buffer.from(inflate(input));
} }
static async read(reader) { static read(reader) {
const constructor = reader.readInt(false); const constructor = reader.readInt(false);
if (constructor !== GZIPPacked.CONSTRUCTOR_ID) { if (constructor !== GZIPPacked.CONSTRUCTOR_ID) {
throw new Error('not equal'); throw new Error('not equal');
} }
return await GZIPPacked.gzip(reader.tgReadBytes()); return GZIPPacked.gzip(reader.tgReadBytes());
} }
static async fromReader(reader) { static async fromReader(reader) {

View File

@ -26,16 +26,16 @@ class MessageContainer {
this.classType = 'constructor'; this.classType = 'constructor';
} }
static async fromReader(reader) { static fromReader(reader) {
const messages = []; const messages = [];
const length = reader.readInt(); const length = reader.readInt();
for (let x = 0; x < length; x++) { for (let x = 0; x < length; x++) {
const msgId = reader.readLong(); const msgId = reader.readLong();
const seqNo = reader.readInt(); const seqNo = reader.readInt();
const length = reader.readInt(); const containerLength = reader.readInt();
const before = reader.tellPosition(); const before = reader.tellPosition();
const obj = reader.tgReadObject(); const obj = reader.tgReadObject();
reader.setPosition(before + length); reader.setPosition(before + containerLength);
const tlMessage = new TLMessage(msgId, seqNo, obj); const tlMessage = new TLMessage(msgId, seqNo, obj);
messages.push(tlMessage); messages.push(tlMessage);
} }

View File

@ -18,7 +18,7 @@ class RPCResult {
const msgId = reader.readLong(); const msgId = reader.readLong();
const innerCode = reader.readInt(false); const innerCode = reader.readInt(false);
if (innerCode === RpcError.CONSTRUCTOR_ID) { if (innerCode === RpcError.CONSTRUCTOR_ID) {
return new RPCResult(msgId, null, RpcError.fromReader(reader)); return new RPCResult(msgId, undefined, RpcError.fromReader(reader));
} }
if (innerCode === GZIPPacked.CONSTRUCTOR_ID) { if (innerCode === GZIPPacked.CONSTRUCTOR_ID) {
return new RPCResult(msgId, (await GZIPPacked.fromReader(reader)).data); return new RPCResult(msgId, (await GZIPPacked.fromReader(reader)).data);
@ -27,7 +27,7 @@ class RPCResult {
// This reader.read() will read more than necessary, but it's okay. // This reader.read() will read more than necessary, but it's okay.
// We could make use of MessageContainer's length here, but since // We could make use of MessageContainer's length here, but since
// it's not necessary we don't need to care about it. // it's not necessary we don't need to care about it.
return new RPCResult(msgId, reader.read(), null); return new RPCResult(msgId, reader.read(), undefined);
} }
} }

View File

@ -44,7 +44,7 @@ function makeCRCTable() {
return crcTable; return crcTable;
} }
let crcTable = null; let crcTable;
function crc32(buf) { function crc32(buf) {
if (!crcTable) { if (!crcTable) {
@ -62,6 +62,21 @@ function crc32(buf) {
return (crc ^ (-1)) >>> 0; return (crc ^ (-1)) >>> 0;
} }
const findAll = (regex, str, matches = []) => {
if (!regex.flags.includes('g')) {
regex = new RegExp(regex.source, 'g');
}
const res = regex.exec(str);
if (res) {
matches.push(res.slice(1));
findAll(regex, str, matches);
}
return matches;
};
const fromLine = (line, isFunction) => { const fromLine = (line, isFunction) => {
const match = line.match(/([\w.]+)(?:#([0-9a-fA-F]+))?(?:\s{?\w+:[\w\d<>#.?!]+}?)*\s=\s([\w\d<>#.?]+);$/); const match = line.match(/([\w.]+)(?:#([0-9a-fA-F]+))?(?:\s{?\w+:[\w\d<>#.?!]+}?)*\s=\s([\w\d<>#.?]+);$/);
if (!match) { if (!match) {
@ -77,7 +92,7 @@ const fromLine = (line, isFunction) => {
subclassOfId: crc32(match[3]), subclassOfId: crc32(match[3]),
result: match[3], result: match[3],
isFunction, isFunction,
namespace: null, namespace: undefined,
}; };
if (!currentConfig.constructorId) { if (!currentConfig.constructorId) {
const hexId = ''; const hexId = '';
@ -134,16 +149,10 @@ function buildArgConfig(name, argType) {
skipConstructorId: false, skipConstructorId: false,
flagIndex: -1, flagIndex: -1,
flagIndicator: true, flagIndicator: true,
type: null, type: undefined,
useVectorId: null, useVectorId: undefined,
}; };
// Special case: some types can be inferred, which makes it
// less annoying to type. Currently the only type that can
// be inferred is if the name is 'random_id', to which a
// random ID will be assigned if left as None (the default)
const canBeInferred = name === 'random_id';
// The type can be an indicator that other arguments will be flags // The type can be an indicator that other arguments will be flags
if (argType !== '#') { if (argType !== '#') {
currentConfig.flagIndicator = false; currentConfig.flagIndicator = false;
@ -206,8 +215,8 @@ function buildArgConfig(name, argType) {
} }
const parseTl = function* (content, layer, methods = [], ignoreIds = CORE_TYPES) { function* parseTl(content, layer, methods = [], ignoreIds = CORE_TYPES) {
const methodInfo = (methods || []).reduce((o, m) => ({ (methods || []).reduce((o, m) => ({
...o, ...o,
[m.name]: m, [m.name]: m,
}), {}); }), {});
@ -281,22 +290,7 @@ const parseTl = function* (content, layer, methods = [], ignoreIds = CORE_TYPES)
for (const obj of objAll) { for (const obj of objAll) {
yield obj; yield obj;
} }
}; }
const findAll = (regex, str, matches = []) => {
if (!regex.flags.includes('g')) {
regex = new RegExp(regex.source, 'g');
}
const res = regex.exec(str);
if (res) {
matches.push(res.slice(1));
findAll(regex, str, matches);
}
return matches;
};
function serializeBytes(data) { function serializeBytes(data) {
if (!(data instanceof Buffer)) { if (!(data instanceof Buffer)) {

View File

@ -4,13 +4,10 @@ const {
serializeDate, serializeDate,
} = require('./generationHelpers'); } = require('./generationHelpers');
const patched = null;
module.exports = { module.exports = {
// TODO Refactor internal usages to always use `api`. // TODO Refactor internal usages to always use `api`.
constructors: api, constructors: api,
requests: api, requests: api,
patched,
serializeBytes, serializeBytes,
serializeDate, serializeDate,
}; };