GramJs: Fix ESLint errors (#1070)
This commit is contained in:
parent
4faa7563aa
commit
b36ec8cf44
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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'];
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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 '
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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 {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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)) {
|
||||||
|
|||||||
@ -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');
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ class AbridgedPacketCodec extends PacketCodec {
|
|||||||
.readInt32LE(0);
|
.readInt32LE(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return await reader.read(length << 2);
|
return reader.read(length << 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 = {};
|
||||||
|
|||||||
@ -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');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)) {
|
||||||
|
|||||||
@ -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,
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user