From eb585fc3f106d242edf0917d82220f5ee876fe83 Mon Sep 17 00:00:00 2001 From: Alina Sireneva Date: Sat, 10 Jun 2023 00:37:26 +0300 Subject: [PATCH] build: fixes after rebase --- .../client/src/methods/auth/check-password.ts | 6 +- packages/client/src/methods/auth/send-code.ts | 2 +- .../client/src/methods/auth/sign-in-bot.ts | 8 +- packages/client/src/methods/auth/sign-in.ts | 6 +- packages/client/src/methods/auth/sign-up.ts | 6 +- .../client/src/methods/auth/start-test.ts | 1 + packages/client/src/methods/auth/start.ts | 3 +- .../src/methods/files/download-iterable.ts | 152 +++++++++--------- .../src/methods/messages/normalize-inline.ts | 24 +-- packages/client/src/methods/updates.ts | 15 +- packages/core/src/base-client.ts | 126 +++------------ packages/core/src/network/auth-key.ts | 35 ++-- packages/core/src/network/authorization.ts | 6 +- packages/core/src/network/config-manager.ts | 3 +- packages/core/src/network/mtproto-session.ts | 28 ++-- .../src/network/multi-session-connection.ts | 37 +++-- packages/core/src/network/network-manager.ts | 46 +++--- .../core/src/network/persistent-connection.ts | 3 - .../core/src/network/session-connection.ts | 98 ++++++----- packages/core/src/storage/memory.ts | 6 +- packages/core/src/utils/logger.ts | 8 +- packages/core/src/utils/long-utils.ts | 4 +- packages/sqlite/index.ts | 15 +- 23 files changed, 301 insertions(+), 337 deletions(-) diff --git a/packages/client/src/methods/auth/check-password.ts b/packages/client/src/methods/auth/check-password.ts index 736d2d4e..08a1f9d6 100644 --- a/packages/client/src/methods/auth/check-password.ts +++ b/packages/client/src/methods/auth/check-password.ts @@ -47,8 +47,10 @@ export async function checkPassword( await this._saveStorage() // telegram ignores invokeWithoutUpdates for auth methods - if (this._disableUpdates) this.primaryConnection._resetSession() - else this.startUpdatesLoop() + // todo where is this._disableUpdates? + // if (this._disableUpdates) this.primaryConnection._resetSession() + // else + this.startUpdatesLoop() return new User(this, res.user) } diff --git a/packages/client/src/methods/auth/send-code.ts b/packages/client/src/methods/auth/send-code.ts index a6eec87e..88548b87 100644 --- a/packages/client/src/methods/auth/send-code.ts +++ b/packages/client/src/methods/auth/send-code.ts @@ -19,7 +19,7 @@ export async function sendCode( const res = await this.call({ _: 'auth.sendCode', phoneNumber: phone, - apiId: this._initConnectionParams.apiId, + apiId: this.network._initConnectionParams.apiId, apiHash: this._apiHash, settings: { _: 'codeSettings' }, }) diff --git a/packages/client/src/methods/auth/sign-in-bot.ts b/packages/client/src/methods/auth/sign-in-bot.ts index 6262215a..d78a5d07 100644 --- a/packages/client/src/methods/auth/sign-in-bot.ts +++ b/packages/client/src/methods/auth/sign-in-bot.ts @@ -17,7 +17,7 @@ export async function signInBot( const res = await this.call({ _: 'auth.importBotAuthorization', flags: 0, - apiId: this._initConnectionParams.apiId, + apiId: this.network._initConnectionParams.apiId, apiHash: this._apiHash, botAuthToken: token, }) @@ -42,8 +42,10 @@ export async function signInBot( await this._saveStorage() // telegram ignores invokeWithoutUpdates for auth methods - if (this._disableUpdates) this.primaryConnection._resetSession() - else this.startUpdatesLoop() + // todo where is this._disableUpdates? + // if (this._disableUpdates) this.primaryConnection._resetSession() + // else + this.startUpdatesLoop() return new User(this, res.user) } diff --git a/packages/client/src/methods/auth/sign-in.ts b/packages/client/src/methods/auth/sign-in.ts index a443279e..e5982233 100644 --- a/packages/client/src/methods/auth/sign-in.ts +++ b/packages/client/src/methods/auth/sign-in.ts @@ -50,8 +50,10 @@ export async function signIn( await this._saveStorage() // telegram ignores invokeWithoutUpdates for auth methods - if (this._disableUpdates) this.primaryConnection._resetSession() - else this.startUpdatesLoop() + // todo where is this._disableUpdates? + // if (this._disableUpdates) this.primaryConnection._resetSession() + // else + this.startUpdatesLoop() return new User(this, res.user) } diff --git a/packages/client/src/methods/auth/sign-up.ts b/packages/client/src/methods/auth/sign-up.ts index fcff30f8..7b98fc98 100644 --- a/packages/client/src/methods/auth/sign-up.ts +++ b/packages/client/src/methods/auth/sign-up.ts @@ -40,8 +40,10 @@ export async function signUp( await this._saveStorage() // telegram ignores invokeWithoutUpdates for auth methods - if (this._disableUpdates) this.primaryConnection._resetSession() - else this.startUpdatesLoop() + // todo where is this._disableUpdates? + // if (this._disableUpdates) this.primaryConnection._resetSession() + // else + this.startUpdatesLoop() return new User(this, res.user) } diff --git a/packages/client/src/methods/auth/start-test.ts b/packages/client/src/methods/auth/start-test.ts index 6b272154..9b8e2d42 100644 --- a/packages/client/src/methods/auth/start-test.ts +++ b/packages/client/src/methods/auth/start-test.ts @@ -79,6 +79,7 @@ export async function startTest( if (!availableDcs.find((dc) => dc.id === id)) { throw new MtArgumentError(`${phone} has invalid DC ID (${id})`) } } else { let dcId = this._defaultDc.id + if (params.dcId) { if (!availableDcs.find((dc) => dc.id === params!.dcId)) { throw new MtArgumentError(`DC ID is invalid (${dcId})`) } dcId = params.dcId diff --git a/packages/client/src/methods/auth/start.ts b/packages/client/src/methods/auth/start.ts index 6e8ab4ce..cd7f6327 100644 --- a/packages/client/src/methods/auth/start.ts +++ b/packages/client/src/methods/auth/start.ts @@ -155,7 +155,8 @@ export async function start( me.isBot, ) - if (!this._disableUpdates) { + // todo where is this._disableUpdates? + if (!false) { this._catchUpChannels = Boolean(params.catchUp) if (!params.catchUp) { diff --git a/packages/client/src/methods/files/download-iterable.ts b/packages/client/src/methods/files/download-iterable.ts index e2433beb..1177ce76 100644 --- a/packages/client/src/methods/files/download-iterable.ts +++ b/packages/client/src/methods/files/download-iterable.ts @@ -10,7 +10,6 @@ import { FileDownloadParameters, FileLocation, MtArgumentError, - MtUnsupportedError, } from '../../types' import { determinePartSize } from '../../utils/file-utils' @@ -36,7 +35,7 @@ export async function* downloadAsIterable( ) } - let offset = params.offset ?? 0 + const offset = params.offset ?? 0 if (offset % 4096 !== 0) { throw new MtArgumentError( @@ -80,7 +79,7 @@ export async function* downloadAsIterable( const chunkSize = partSizeKb * 1024 - let limit = + const limit = params.limit ?? // derive limit from chunk size, file size and offset (fileSize ? @@ -88,78 +87,81 @@ export async function* downloadAsIterable( // we will receive an error when we have reached the end anyway Infinity) - let connection = this._downloadConnections[dcId] + // fixme + throw new Error('TODO') - if (!connection) { - connection = await this.createAdditionalConnection(dcId) - this._downloadConnections[dcId] = connection - } + // let connection = this._downloadConnections[dcId] - const requestCurrent = async (): Promise => { - let result: - | tl.RpcCallReturn['upload.getFile'] - | tl.RpcCallReturn['upload.getWebFile'] - - try { - result = await this.call( - { - _: isWeb ? 'upload.getWebFile' : 'upload.getFile', - // eslint-disable-next-line @typescript-eslint/no-explicit-any - location: location as any, - offset, - limit: chunkSize, - }, - { connection }, - ) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } catch (e: any) { - if (e.constructor === tl.errors.FileMigrateXError) { - connection = this._downloadConnections[e.new_dc] - - if (!connection) { - connection = await this.createAdditionalConnection(e.new_dc) - this._downloadConnections[e.new_dc] = connection - } - - return requestCurrent() - } else if (e.constructor === tl.errors.FilerefUpgradeNeededError) { - // todo: implement someday - // see: https://github.com/LonamiWebs/Telethon/blob/0e8bd8248cc649637b7c392616887c50986427a0/telethon/client/downloads.py#L99 - throw new MtUnsupportedError('File ref expired!') - } else throw e - } - - if (result._ === 'upload.fileCdnRedirect') { - // we shouldnt receive them since cdnSupported is not set in the getFile request. - // also, i couldnt find any media that would be downloaded from cdn, so even if - // i implemented that, i wouldnt be able to test that, so :shrug: - throw new MtUnsupportedError( - 'Received CDN redirect, which is not supported (yet)', - ) - } - - if ( - result._ === 'upload.webFile' && - result.size && - limit === Infinity - ) { - limit = result.size - } - - return result.bytes - } - - for (let i = 0; i < limit; i++) { - const buf = await requestCurrent() - - if (buf.length === 0) { - // we've reached the end - return - } - - yield buf - offset += chunkSize - - params.progressCallback?.(offset, limit) - } + // if (!connection) { + // connection = await this.createAdditionalConnection(dcId) + // this._downloadConnections[dcId] = connection + // } + // + // const requestCurrent = async (): Promise => { + // let result: + // | tl.RpcCallReturn['upload.getFile'] + // | tl.RpcCallReturn['upload.getWebFile'] + // + // try { + // result = await this.call( + // { + // _: isWeb ? 'upload.getWebFile' : 'upload.getFile', + // // eslint-disable-next-line @typescript-eslint/no-explicit-any + // location: location as any, + // offset, + // limit: chunkSize, + // }, + // { connection }, + // ) + // // eslint-disable-next-line @typescript-eslint/no-explicit-any + // } catch (e: any) { + // if (e.constructor === tl.errors.FileMigrateXError) { + // connection = this._downloadConnections[e.new_dc] + // + // if (!connection) { + // connection = await this.createAdditionalConnection(e.new_dc) + // this._downloadConnections[e.new_dc] = connection + // } + // + // return requestCurrent() + // } else if (e.constructor === tl.errors.FilerefUpgradeNeededError) { + // // todo: implement someday + // // see: https://github.com/LonamiWebs/Telethon/blob/0e8bd8248cc649637b7c392616887c50986427a0/telethon/client/downloads.py#L99 + // throw new MtUnsupportedError('File ref expired!') + // } else throw e + // } + // + // if (result._ === 'upload.fileCdnRedirect') { + // // we shouldnt receive them since cdnSupported is not set in the getFile request. + // // also, i couldnt find any media that would be downloaded from cdn, so even if + // // i implemented that, i wouldnt be able to test that, so :shrug: + // throw new MtUnsupportedError( + // 'Received CDN redirect, which is not supported (yet)', + // ) + // } + // + // if ( + // result._ === 'upload.webFile' && + // result.size && + // limit === Infinity + // ) { + // limit = result.size + // } + // + // return result.bytes + // } + // + // for (let i = 0; i < limit; i++) { + // const buf = await requestCurrent() + // + // if (buf.length === 0) { + // // we've reached the end + // return + // } + // + // yield buf + // offset += chunkSize + // + // params.progressCallback?.(offset, limit) + // } } diff --git a/packages/client/src/methods/messages/normalize-inline.ts b/packages/client/src/methods/messages/normalize-inline.ts index 1fad930f..dc611f66 100644 --- a/packages/client/src/methods/messages/normalize-inline.ts +++ b/packages/client/src/methods/messages/normalize-inline.ts @@ -23,15 +23,17 @@ export async function _normalizeInline( id = parseInlineMessageId(id) } - let connection = this.primaryConnection - - if (id.dcId !== connection.params.dc.id) { - if (!(id.dcId in this._connectionsForInline)) { - this._connectionsForInline[id.dcId] = - await this.createAdditionalConnection(id.dcId) - } - connection = this._connectionsForInline[id.dcId] - } - - return [id, connection] + // let connection = this.primaryConnection + // + // if (id.dcId !== connection.params.dc.id) { + // if (!(id.dcId in this._connectionsForInline)) { + // this._connectionsForInline[id.dcId] = + // await this.createAdditionalConnection(id.dcId) + // } + // connection = this._connectionsForInline[id.dcId] + // } + // + // return [id, connection] + // fixme + throw new Error('TODO') } diff --git a/packages/client/src/methods/updates.ts b/packages/client/src/methods/updates.ts index 9b522229..de140525 100644 --- a/packages/client/src/methods/updates.ts +++ b/packages/client/src/methods/updates.ts @@ -1211,15 +1211,16 @@ async function _onUpdate( // we just needed to apply new pts values return case 'updateDcOptions': - if (!this._config) { - this._config = await this.call({ _: 'help.getConfig' }) - } else { - (this._config as tl.Mutable).dcOptions = - upd.dcOptions - } + // fixme - forward to ConfigManager + // if (!this._config) { + // this._config = await this.call({ _: 'help.getConfig' }) + // } else { + // (this._config as tl.Mutable).dcOptions = + // upd.dcOptions + // } break case 'updateConfig': - this._config = await this.call({ _: 'help.getConfig' }) + // this._config = await this.call({ _: 'help.getConfig' }) break case 'updateUserName': if (upd.userId === this._userId) { diff --git a/packages/core/src/base-client.ts b/packages/core/src/base-client.ts index 44770b95..949857ef 100644 --- a/packages/core/src/base-client.ts +++ b/packages/core/src/base-client.ts @@ -7,16 +7,13 @@ import defaultReaderMap from '@mtcute/tl/binary/reader' import defaultWriterMap from '@mtcute/tl/binary/writer' import { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime' -import defaultReaderMap from '@mtcute/tl/binary/reader' -import defaultWriterMap from '@mtcute/tl/binary/writer' - import { - defaultReconnectionStrategy, - defaultTransportFactory, ReconnectionStrategy, SessionConnection, TransportFactory, } from './network' +import { ConfigManager } from './network/config-manager' +import { NetworkManager, NetworkManagerExtraParams } from './network/network-manager' import { PersistentConnectionParams } from './network/persistent-connection' import { ITelegramStorage, MemoryStorage } from './storage' import { MustEqual } from './types' @@ -25,10 +22,6 @@ import { createControllablePromise, CryptoProviderFactory, defaultCryptoProviderFactory, - sleep, - getAllPeersFrom, - LogManager, - toggleChannelIdMark, defaultProductionDc, defaultProductionIpv6Dc, defaultTestDc, @@ -36,28 +29,11 @@ import { getAllPeersFrom, ICryptoProvider, LogManager, + readStringSession, sleep, toggleChannelIdMark, - ControllablePromise, - createControllablePromise, - readStringSession, - writeStringSession + writeStringSession, } from './utils' -import { addPublicKey } from './utils/crypto/keys' -import { readStringSession, writeStringSession } from './utils/string-session' - -import { - TransportFactory, - defaultReconnectionStrategy, - ReconnectionStrategy, - defaultTransportFactory, - SessionConnection, -} from './network' -import { PersistentConnectionParams } from './network/persistent-connection' -import { ITelegramStorage, MemoryStorage } from './storage' - -import { ConfigManager } from './network/config-manager' -import { NetworkManager, NetworkManagerExtraParams } from "./network/network-manager"; export interface BaseTelegramClientOptions { /** @@ -184,7 +160,7 @@ export interface BaseTelegramClientOptions { /** * **EXPERT USE ONLY!** * - * Override TL layer used for the connection. /;' + * Override TL layer used for the connection. * * **Does not** change the schema used. */ @@ -207,42 +183,42 @@ export interface BaseTelegramClientOptions { export class BaseTelegramClient extends EventEmitter { /** - * Crypto provider taken from {@link BaseTelegramClient.Options.crypto} + * Crypto provider taken from {@link BaseTelegramClientOptions.crypto} */ protected readonly _crypto: ICryptoProvider /** - * Telegram storage taken from {@link BaseTelegramClient.Options.storage} + * Telegram storage taken from {@link BaseTelegramClientOptions.storage} */ readonly storage: ITelegramStorage /** - * API hash taken from {@link BaseTelegramClient.Options.apiHash} + * API hash taken from {@link BaseTelegramClientOptions.apiHash} */ protected readonly _apiHash: string /** - * "Use IPv6" taken from {@link BaseTelegramClient.Options.useIpv6} + * "Use IPv6" taken from {@link BaseTelegramClientOptions.useIpv6} */ protected readonly _useIpv6: boolean /** - * "Test mode" taken from {@link BaseTelegramClient.Options.testMode} + * "Test mode" taken from {@link BaseTelegramClientOptions.testMode} */ protected readonly _testMode: boolean /** - * Flood sleep threshold taken from {@link BaseTelegramClient.Options.floodSleepThreshold} + * Flood sleep threshold taken from {@link BaseTelegramClientOptions.floodSleepThreshold} */ protected readonly _floodSleepThreshold: number /** - * RPC retry count taken from {@link BaseTelegramClient.Options.rpcRetryCount} + * RPC retry count taken from {@link BaseTelegramClientOptions.rpcRetryCount} */ protected readonly _rpcRetryCount: number /** - * Primary DC taken from {@link BaseTelegramClient.Options.defaultDc}, + * Primary DC taken from {@link BaseTelegramClientOptions.defaultDc}, * loaded from session or changed by other means (like redirecting). */ protected _defaultDc: tl.RawDcOption @@ -256,7 +232,7 @@ export class BaseTelegramClient extends EventEmitter { private _floodWaitedRequests: Record = {} protected _config = new ConfigManager(() => - this.call({ _: 'help.getConfig' }) + this.call({ _: 'help.getConfig' }), ) private _additionalConnections: SessionConnection[] = [] @@ -311,8 +287,6 @@ export class BaseTelegramClient extends EventEmitter { } this._defaultDc = dc - this._reconnectionStrategy = - opts.reconnectionStrategy ?? defaultReconnectionStrategy this._floodSleepThreshold = opts.floodSleepThreshold ?? 10000 this._rpcRetryCount = opts.rpcRetryCount ?? 5 this._niceStacks = opts.niceStacks ?? true @@ -350,72 +324,6 @@ export class BaseTelegramClient extends EventEmitter { await this.storage.save?.() } - protected _keepAliveAction(): void { - if (this._disableUpdates) return - - // telegram asks to fetch pending updates - // if there are no updates for 15 minutes. - // core does not have update handling, - // so we just use getState so the server knows - // we still do need updates - this.call({ _: 'updates.getState' }).catch((e) => { - if (!(e instanceof tl.errors.RpcError)) { - this.primaryConnection.reconnect() - } - }) - } - - private _cleanupPrimaryConnection(forever = false): void { - if (forever && this.primaryConnection) this.primaryConnection.destroy() - if (this._keepAliveInterval) clearInterval(this._keepAliveInterval) - } - - private _setupPrimaryConnection(): void { - this._cleanupPrimaryConnection(true) - - this.primaryConnection = new SessionConnection( - { - crypto: this._crypto, - initConnection: this._initConnectionParams, - transportFactory: this._transportFactory, - dc: this._primaryDc, - testMode: this._testMode, - reconnectionStrategy: this._reconnectionStrategy, - layer: this._layer, - disableUpdates: this._disableUpdates, - readerMap: this._readerMap, - writerMap: this._writerMap, - }, - this.log.create('connection'), - ) - - this.primaryConnection.on('usable', () => { - this._lastUpdateTime = Date.now() - - if (this._keepAliveInterval) clearInterval(this._keepAliveInterval) - this._keepAliveInterval = setInterval(async () => { - if (Date.now() - this._lastUpdateTime > 900_000) { - this._keepAliveAction() - this._lastUpdateTime = Date.now() - } - }, 60_000) - }) - this.primaryConnection.on('update', (update) => { - this._lastUpdateTime = Date.now() - this._handleUpdate(update) - }) - this.primaryConnection.on('wait', () => - this._cleanupPrimaryConnection(), - ) - this.primaryConnection.on('key-change', async (key) => { - this.storage.setAuthKeyFor(this._primaryDc.id, key) - await this._saveStorage() - }) - this.primaryConnection.on('error', (err) => - this._emitError(err, this.primaryConnection), - ) - } - /** * Initialize the connection to the primary DC. * @@ -475,7 +383,7 @@ export class BaseTelegramClient extends EventEmitter { * Wait until this client is usable (i.e. connection is fully ready) */ async waitUntilUsable(): Promise { - return new Promise((resolve) => { + return new Promise((_resolve) => { // todo // this.primaryConnection.once('usable', resolve) }) @@ -572,6 +480,8 @@ export class BaseTelegramClient extends EventEmitter { for (let i = 0; i < this._rpcRetryCount; i++) { try { + // fixme temporary hack + // eslint-disable-next-line dot-notation const res = await this.network['_primaryDc']!.mainConnection.sendRpc( message, stack, @@ -915,7 +825,7 @@ export class BaseTelegramClient extends EventEmitter { self: await this.storage.getSelf(), testMode: this._testMode, primaryDc: this._defaultDc, - authKey: Buffer.from([]) //this.primaryConnection.getAuthKey()!, + authKey: Buffer.from([]), //this.primaryConnection.getAuthKey()!, }) } diff --git a/packages/core/src/network/auth-key.ts b/packages/core/src/network/auth-key.ts index 55da0f5d..d2e5f690 100644 --- a/packages/core/src/network/auth-key.ts +++ b/packages/core/src/network/auth-key.ts @@ -1,8 +1,10 @@ -import { TlBinaryReader, TlReaderMap } from '@mtcute/tl-runtime' -import { buffersEqual, ICryptoProvider, Logger, randomBytes } from '../utils' import Long from 'long' -import { createAesIgeForMessage } from '../utils/crypto/mtproto' + import { tl } from '@mtcute/tl' +import { TlBinaryReader, TlReaderMap } from '@mtcute/tl-runtime' + +import { buffersEqual, ICryptoProvider, Logger, randomBytes } from '../utils' +import { createAesIgeForMessage } from '../utils/crypto/mtproto' export class AuthKey { ready = false @@ -15,7 +17,7 @@ export class AuthKey { constructor( readonly _crypto: ICryptoProvider, readonly log: Logger, - readonly _readerMap: TlReaderMap + readonly _readerMap: TlReaderMap, ) {} match(keyId: Buffer): boolean { @@ -37,7 +39,7 @@ export class AuthKey { async encryptMessage( message: Buffer, serverSalt: Long, - sessionId: Long + sessionId: Long, ): Promise { if (!this.ready) throw new Error('Keys are not set up!') @@ -61,7 +63,7 @@ export class AuthKey { this._crypto, this.key, messageKey, - true + true, ) const encryptedData = await ige.encrypt(buf) @@ -71,7 +73,7 @@ export class AuthKey { async decryptMessage( data: Buffer, sessionId: Long, - callback: (msgId: tl.Long, seqNo: number, data: TlBinaryReader) => void + callback: (msgId: tl.Long, seqNo: number, data: TlBinaryReader) => void, ): Promise { const messageKey = data.slice(8, 24) const encryptedData = data.slice(24) @@ -80,13 +82,13 @@ export class AuthKey { this._crypto, this.key, messageKey, - false + false, ) const innerData = await ige.decrypt(encryptedData) const expectedMessageKey = ( await this._crypto.sha256( - Buffer.concat([this.serverSalt, innerData]) + Buffer.concat([this.serverSalt, innerData]), ) ).slice(8, 24) @@ -94,8 +96,9 @@ export class AuthKey { this.log.warn( '[%h] received message with invalid messageKey = %h (expected %h)', messageKey, - expectedMessageKey + expectedMessageKey, ) + return } @@ -107,8 +110,9 @@ export class AuthKey { if (sessionId_.neq(sessionId)) { this.log.warn( 'ignoring message with invalid sessionId = %h', - sessionId_ + sessionId_, ) + return } @@ -119,16 +123,18 @@ export class AuthKey { this.log.warn( 'ignoring message with invalid length: %d > %d', length, - innerData.length - 32 + innerData.length - 32, ) + return } if (length % 4 !== 0) { this.log.warn( 'ignoring message with invalid length: %d is not a multiple of 4', - length + length, ) + return } @@ -137,8 +143,9 @@ export class AuthKey { if (paddingSize < 12 || paddingSize > 1024) { this.log.warn( 'ignoring message with invalid padding size: %d', - paddingSize + paddingSize, ) + return } diff --git a/packages/core/src/network/authorization.ts b/packages/core/src/network/authorization.ts index c8e4f039..03b4bb8a 100644 --- a/packages/core/src/network/authorization.ts +++ b/packages/core/src/network/authorization.ts @@ -102,7 +102,7 @@ async function rsaEncrypt( export async function doAuthorization( connection: SessionConnection, crypto: ICryptoProvider, - expiresIn?: number + expiresIn?: number, ): Promise<[Buffer, Long, number]> { // eslint-disable-next-line dot-notation const session = connection['_session'] @@ -130,7 +130,7 @@ export async function doAuthorization( return TlBinaryReader.deserializeObject( readerMap, await connection.waitForUnencryptedMessage(), - 20 // skip mtproto header + 20, // skip mtproto header ) } @@ -186,7 +186,7 @@ export async function doAuthorization( newNonce, serverNonce: resPq.serverNonce, dc: dcId, - expiresIn: expiresIn! // whatever + expiresIn: expiresIn!, // whatever } const pqInnerData = TlBinaryWriter.serializeObject(writerMap, _pqInnerData) diff --git a/packages/core/src/network/config-manager.ts b/packages/core/src/network/config-manager.ts index 54f5381f..35480e12 100644 --- a/packages/core/src/network/config-manager.ts +++ b/packages/core/src/network/config-manager.ts @@ -28,7 +28,7 @@ export class ConfigManager { if (this._updateTimeout) clearTimeout(this._updateTimeout) this._updateTimeout = setTimeout( () => this.update(), - (config.expires - Date.now() / 1000) * 1000 + (config.expires - Date.now() / 1000) * 1000, ) for (const cb of this._listeners) cb(config) @@ -50,6 +50,7 @@ export class ConfigManager { async get(): Promise { if (this.isStale) await this.update() + return this._config! } diff --git a/packages/core/src/network/mtproto-session.ts b/packages/core/src/network/mtproto-session.ts index faedd595..0bed00ec 100644 --- a/packages/core/src/network/mtproto-session.ts +++ b/packages/core/src/network/mtproto-session.ts @@ -8,21 +8,17 @@ import { TlWriterMap, } from '@mtcute/tl-runtime' -import { getRandomInt, ICryptoProvider, Logger, randomLong } from '../utils' -import { buffersEqual, randomBytes } from '../utils/buffer-utils' -import { +import { ControllablePromise, + Deque, + getRandomInt, ICryptoProvider, Logger, - getRandomInt, - randomLong, - ControllablePromise, - LruSet, - Deque, - SortedArray, LongMap, + LruSet, + randomLong, + SortedArray, } from '../utils' import { AuthKey } from './auth-key' -import { createAesIgeForMessage } from '../utils/crypto/mtproto' export interface PendingRpc { method: string @@ -39,7 +35,7 @@ export interface PendingRpc { initConn?: boolean getState?: number cancelled?: boolean - timeout?: number + timeout?: NodeJS.Timeout } export type PendingMessage = @@ -115,7 +111,7 @@ export class MtprotoSession { queuedCancelReq: Long[] = [] getStateSchedule = new SortedArray( [], - (a, b) => a.getState! - b.getState! + (a, b) => a.getState! - b.getState!, ) // requests info @@ -200,9 +196,10 @@ export class MtprotoSession { this.log.debug( 'enqueued %s for sending (msg_id = %s)', rpc.method, - rpc.msgId || 'n/a' + rpc.msgId || 'n/a', ) this.queuedRpc.pushBack(rpc) + return true } @@ -237,19 +234,21 @@ export class MtprotoSession { /** Encrypt a single MTProto message using session's keys */ async encryptMessage(message: Buffer): Promise { const key = this._authKeyTemp.ready ? this._authKeyTemp : this._authKey + return key.encryptMessage(message, this.serverSalt, this._sessionId) } /** Decrypt a single MTProto message using session's keys */ async decryptMessage( data: Buffer, - callback: Parameters[2] + callback: Parameters[2], ): Promise { if (!this._authKey.ready) throw new Error('Keys are not set up!') const authKeyId = data.slice(0, 8) let key: AuthKey + if (this._authKey.match(authKeyId)) { key = this._authKey } else if (this._authKeyTemp.match(authKeyId)) { @@ -264,6 +263,7 @@ export class MtprotoSession { this._authKeyTemp.id, this._authKeyTempSecondary.id, ) + return } diff --git a/packages/core/src/network/multi-session-connection.ts b/packages/core/src/network/multi-session-connection.ts index be4b3892..d18e1634 100644 --- a/packages/core/src/network/multi-session-connection.ts +++ b/packages/core/src/network/multi-session-connection.ts @@ -1,12 +1,13 @@ import EventEmitter from 'events' + import { tl } from '@mtcute/tl' import { Logger } from '../utils' +import { MtprotoSession } from './mtproto-session' import { SessionConnection, SessionConnectionParams, } from './session-connection' -import { MtprotoSession } from './mtproto-session' export class MultiSessionConnection extends EventEmitter { private _log: Logger @@ -16,7 +17,7 @@ export class MultiSessionConnection extends EventEmitter { constructor( readonly params: SessionConnectionParams, private _count: number, - log: Logger + log: Logger, ) { super() this._log = log.create('multi') @@ -38,7 +39,7 @@ export class MultiSessionConnection extends EventEmitter { this._log.debug( 'updating sessions count: %d -> %d', this._sessions.length, - this._count + this._count, ) // there are two cases @@ -52,8 +53,8 @@ export class MultiSessionConnection extends EventEmitter { this.params.crypto, this._log.create('session'), this.params.readerMap, - this.params.writerMap - ) + this.params.writerMap, + ), ) } @@ -75,6 +76,7 @@ export class MultiSessionConnection extends EventEmitter { } this._sessions.splice(this._count) + return } @@ -84,7 +86,7 @@ export class MultiSessionConnection extends EventEmitter { this.params.crypto, this._log.create('session'), this.params.readerMap, - this.params.writerMap + this.params.writerMap, ) // brvh @@ -101,16 +103,17 @@ export class MultiSessionConnection extends EventEmitter { this._log.debug( 'updating connections count: %d -> %d', this._connections.length, - this._count + this._count, ) const newEnforcePfs = this._count > 1 && this.params.isMainConnection const enforcePfsChanged = newEnforcePfs !== this._enforcePfs + if (enforcePfsChanged) { this._log.debug( 'enforcePfs changed: %s -> %s', this._enforcePfs, - newEnforcePfs + newEnforcePfs, ) this._enforcePfs = newEnforcePfs } @@ -123,6 +126,7 @@ export class MultiSessionConnection extends EventEmitter { } this._connections.splice(this._count) + return } @@ -134,16 +138,16 @@ export class MultiSessionConnection extends EventEmitter { // create new connections for (let i = this._connections.length; i < this._count; i++) { - const session = this.params.isMainConnection - ? this._sessions[i] - : this._sessions[0] + const session = this.params.isMainConnection ? + this._sessions[i] : + this._sessions[0] const conn = new SessionConnection( { ...this.params, usePfs: this.params.usePfs || this._enforcePfs, isMainConnection: this.params.isMainConnection && i === 0, }, - session + session, ) conn.on('update', (update) => this.emit('update', update)) @@ -158,7 +162,7 @@ export class MultiSessionConnection extends EventEmitter { } }) conn.on('tmp-key-change', (key, expires) => - this.emit('tmp-key-change', i, key, expires) + this.emit('tmp-key-change', i, key, expires), ) conn.on('auth-begin', () => { this._log.debug('received auth-begin from connection %d', i) @@ -189,12 +193,13 @@ export class MultiSessionConnection extends EventEmitter { sendRpc( request: T, stack?: string, - timeout?: number + timeout?: number, ): Promise { if (this.params.isMainConnection) { // find the least loaded connection let min = Infinity let minIdx = 0 + for (let i = 0; i < this._connections.length; i++) { const conn = this._connections[i] const total = @@ -219,7 +224,7 @@ export class MultiSessionConnection extends EventEmitter { async changeDc(dc: tl.RawDcOption, authKey?: Buffer | null): Promise { await Promise.all( - this._connections.map((conn) => conn.changeDc(dc, authKey)) + this._connections.map((conn) => conn.changeDc(dc, authKey)), ) } @@ -232,7 +237,7 @@ export class MultiSessionConnection extends EventEmitter { async setAuthKey( authKey: Buffer | null, temp = false, - idx = 0 + idx = 0, ): Promise { const session = this._sessions[idx] const key = temp ? session._authKeyTemp : session._authKey diff --git a/packages/core/src/network/network-manager.ts b/packages/core/src/network/network-manager.ts index 3576a507..49f3e0a9 100644 --- a/packages/core/src/network/network-manager.ts +++ b/packages/core/src/network/network-manager.ts @@ -1,20 +1,20 @@ -import { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime' import { tl } from '@mtcute/tl' +import { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime' +import { ITelegramStorage } from '../storage' import { ICryptoProvider, Logger } from '../utils' -import { defaultTransportFactory, TransportFactory } from './transports' +import { ConfigManager } from './config-manager' +import { MultiSessionConnection } from './multi-session-connection' +import { PersistentConnectionParams } from './persistent-connection' import { defaultReconnectionStrategy, ReconnectionStrategy, } from './reconnection' -import { PersistentConnectionParams } from './persistent-connection' -import { ConfigManager } from './config-manager' -import { MultiSessionConnection } from './multi-session-connection' import { SessionConnection, SessionConnectionParams, } from './session-connection' -import { ITelegramStorage } from '../storage' +import { defaultTransportFactory, TransportFactory } from './transports' export type ConnectionKind = 'main' | 'upload' | 'download' | 'download-small' @@ -81,35 +81,36 @@ export class DcConnectionManager { isMainConnection: true, }, this.manager.params.connectionCount?.main ?? 1, - this.manager._log + this.manager._log, ) constructor( readonly manager: NetworkManager, readonly dcId: number, - private _dc: tl.RawDcOption + private _dc: tl.RawDcOption, ) { this._setupMulti(this.mainConnection, 'main') } private _setupMulti( connection: MultiSessionConnection, - kind: ConnectionKind + kind: ConnectionKind, ): void { connection.on('key-change', (idx, key) => { if (kind !== 'main') { // main connection is responsible for authorization, // and keys are then sent to other connections this.manager._log.warn( - 'got key-change from non-main connection' + 'got key-change from non-main connection', ) + return } this.manager._log.debug( 'key change for dc %d from connection %d', this.dcId, - idx + idx, ) this.manager._storage.setAuthKeyFor(this.dcId, key) @@ -119,21 +120,22 @@ export class DcConnectionManager { connection.on('tmp-key-change', (idx, key, expires) => { if (kind !== 'main') { this.manager._log.warn( - 'got tmp-key-change from non-main connection' + 'got tmp-key-change from non-main connection', ) + return } this.manager._log.debug( 'temp key change for dc %d from connection %d', this.dcId, - idx + idx, ) this.manager._storage.setTempAuthKeyFor( this.dcId, idx, key, - expires * 1000 + expires * 1000, ) }) @@ -142,8 +144,9 @@ export class DcConnectionManager { // to avoid them sending requests before auth is complete if (kind !== 'main') { this.manager._log.warn( - 'got auth-begin from non-main connection' + 'got auth-begin from non-main connection', ) + return } @@ -166,7 +169,7 @@ export class DcConnectionManager { for (let i = 0; i < this.mainConnection._sessions.length; i++) { const temp = await this.manager._storage.getAuthKeyFor( this.dcId, - i + i, ) await this.mainConnection.setAuthKey(temp, true, i) } @@ -208,19 +211,23 @@ export class NetworkManager { constructor( readonly params: NetworkManagerParams & NetworkManagerExtraParams, - readonly config: ConfigManager + readonly config: ConfigManager, ) { let deviceModel = 'mtcute on ' let appVersion = 'unknown' if (typeof process !== 'undefined' && typeof require !== 'undefined') { + // eslint-disable-next-line @typescript-eslint/no-var-requires const os = require('os') deviceModel += `${os.type()} ${os.arch()} ${os.release()}` + try { // for production builds + // eslint-disable-next-line @typescript-eslint/no-var-requires appVersion = require('../package.json').version } catch (e) { try { // for development builds (additional /src/ in path) + // eslint-disable-next-line @typescript-eslint/no-var-requires appVersion = require('../../package.json').version } catch (e) {} } @@ -238,6 +245,7 @@ export class NetworkManager { langCode: 'en', ...(params.initConnectionOptions ?? {}), apiId: params.apiId, + // eslint-disable-next-line @typescript-eslint/no-explicit-any query: null as any, } @@ -276,7 +284,7 @@ export class NetworkManager { // this._cleanupPrimaryConnection() // ) dc.mainConnection.on('error', (err, conn) => - this.params._emitError(err, conn) + this.params._emitError(err, conn), ) dc.loadKeys() .catch((e) => this.params._emitError(e)) @@ -297,7 +305,7 @@ export class NetworkManager { this._dcConnections[defaultDc.id] = new DcConnectionManager( this, defaultDc.id, - defaultDc + defaultDc, ) this._switchPrimaryDc(this._dcConnections[defaultDc.id]) } diff --git a/packages/core/src/network/persistent-connection.ts b/packages/core/src/network/persistent-connection.ts index 79f1fbb5..4ca54c94 100644 --- a/packages/core/src/network/persistent-connection.ts +++ b/packages/core/src/network/persistent-connection.ts @@ -2,10 +2,7 @@ import EventEmitter from 'events' import { tl } from '@mtcute/tl' -import { ICryptoProvider, Logger } from '../utils' import { - ControllablePromise, - createControllablePromise, ICryptoProvider, Logger, } from '../utils' diff --git a/packages/core/src/network/session-connection.ts b/packages/core/src/network/session-connection.ts index 320736b2..6096088e 100644 --- a/packages/core/src/network/session-connection.ts +++ b/packages/core/src/network/session-connection.ts @@ -1,5 +1,4 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @typescript-eslint/no-unused-vars */ // will be reworked in MTQ-32 import Long from 'long' @@ -16,30 +15,21 @@ import { gzipDeflate, gzipInflate } from '@mtcute/tl-runtime/src/platform/gzip' import { ControllablePromise, createCancellablePromise, - Deque, + createControllablePromise, EarlyTimer, - Logger, - LongMap, - LruSet, + longFromBuffer, + randomBytes, randomLong, removeFromLongArray, - SortedArray, - EarlyTimer, - ControllablePromise, - createCancellablePromise, - randomBytes, - longFromBuffer, - createControllablePromise, } from '../utils' -import { MtprotoSession, PendingMessage, PendingRpc } from './mtproto-session' +import { createAesIgeForMessageOld } from '../utils/crypto/mtproto' import { doAuthorization } from './authorization' -import { MtprotoSession } from './mtproto-session' +import { MtprotoSession, PendingMessage, PendingRpc } from './mtproto-session' import { PersistentConnection, PersistentConnectionParams, } from './persistent-connection' import { TransportError } from './transports' -import { createAesIgeForMessageOld } from '../utils/crypto/mtproto' const TEMP_AUTH_KEY_EXPIRY = 86400 @@ -102,7 +92,7 @@ export class SessionConnection extends PersistentConnection { constructor( params: SessionConnectionParams, - readonly _session: MtprotoSession + readonly _session: MtprotoSession, ) { super(params, _session.log.create('conn')) this._flushTimer.onTimeout(this._flush.bind(this)) @@ -122,6 +112,7 @@ export class SessionConnection extends PersistentConnection { const key = temp ? this._session._authKeyTemp : this._session._authKey if (!key.ready) return null + return key.key } @@ -130,6 +121,7 @@ export class SessionConnection extends PersistentConnection { this.log.debug('use pfs changed to %s', usePfs) this._usePfs = usePfs + if (!usePfs) { this._isPfsBindingPending = false this._isPfsBindingPendingInBackground = false @@ -174,12 +166,14 @@ export class SessionConnection extends PersistentConnection { if (!this._session._authKey.ready) { if (!this.params.isMainConnection) { this.log.info('no auth key, waiting for main connection') + // once it is done, we will be notified return } this.log.info('no perm auth key, authorizing...') this._authorize() + // todo: if we use pfs, we can also start temp key exchange here return } @@ -187,6 +181,7 @@ export class SessionConnection extends PersistentConnection { if (this._usePfs && !this._session._authKeyTemp.ready) { this.log.info('no temp auth key but using pfs, authorizing') this._authorizePfs() + return } @@ -219,11 +214,13 @@ export class SessionConnection extends PersistentConnection { this._session._authKeyTemp.reset() this._authorizePfs() this._onAllFailed('temp key expired, binding started') + return } else if (this._isPfsBindingPending) { this.log.info('transport error 404, pfs binding in progress') this._onAllFailed('temp key expired, binding pending') + return } @@ -276,6 +273,7 @@ export class SessionConnection extends PersistentConnection { _authorize(): void { if (this._session.authorizationPending) { this.log.info('_authorize(): authorization already in progress') + return } @@ -283,6 +281,7 @@ export class SessionConnection extends PersistentConnection { // we don't authorize on non-main connections this.log.debug('_authorize(): non-main connection, requesting...') this.emit('request-auth') + return } @@ -301,9 +300,8 @@ export class SessionConnection extends PersistentConnection { if (this._usePfs) { return this._authorizePfs() - } else { - this.onConnectionUsable() } + this.onConnectionUsable() }) .catch((err) => { this._session.authorizationPending = false @@ -315,6 +313,7 @@ export class SessionConnection extends PersistentConnection { private _authorizePfs(background = false): void { if (this._isPfsBindingPending) return + if (this._pfsUpdateTimeout) { clearTimeout(this._pfsUpdateTimeout) this._pfsUpdateTimeout = undefined @@ -326,6 +325,7 @@ export class SessionConnection extends PersistentConnection { // current operation to complete this._isPfsBindingPendingInBackground = false this._isPfsBindingPending = true + return } @@ -339,6 +339,7 @@ export class SessionConnection extends PersistentConnection { .then(async ([tempAuthKey, tempServerSalt]) => { if (!this._usePfs) { this.log.info('pfs has been disabled while generating temp key') + return } @@ -351,7 +352,7 @@ export class SessionConnection extends PersistentConnection { 'binding temp_auth_key (%h) to perm_auth_key (%h), msg_id = %l...', tempKey.id, this._session._authKey.id, - msgId + msgId, ) // we now need to bind the key @@ -387,7 +388,7 @@ export class SessionConnection extends PersistentConnection { this.params.crypto, this._session._authKey.key, msgKey, - true + true, ) const encryptedData = await ige.encrypt(msgWithPadding) const encryptedMessage = Buffer.concat([ @@ -396,7 +397,7 @@ export class SessionConnection extends PersistentConnection { encryptedData, ]) - const promise = createControllablePromise() + const promise = createControllablePromise() // encrypt the message using temp key and same msg id // this is a bit of a hack, but it works @@ -424,11 +425,11 @@ export class SessionConnection extends PersistentConnection { } const reqSize = TlSerializationCounter.countNeededBytes( this._writerMap, - request + request, ) const reqWriter = TlBinaryWriter.alloc( this._writerMap, - reqSize + 16 + reqSize + 16, ) reqWriter.long(this._registerOutgoingMsgId(msgId)) reqWriter.uint(this._session.getSeqNo()) @@ -439,16 +440,17 @@ export class SessionConnection extends PersistentConnection { const requestEncrypted = await tempKey.encryptMessage( reqWriter.result(), tempServerSalt, - this._session._sessionId + this._session._sessionId, ) await this.send(requestEncrypted) - const res: mtp.RawMt_rpc_error | boolean = await promise + const res = await promise this._session.pendingMessages.delete(msgId) if (!this._usePfs) { this.log.info('pfs has been disabled while binding temp key') + return } @@ -456,7 +458,7 @@ export class SessionConnection extends PersistentConnection { this.log.error( 'failed to bind temp key: %s:%s', res.errorCode, - res.errorMessage + res.errorMessage, ) throw new Error('Failed to bind temporary key') } @@ -470,7 +472,7 @@ export class SessionConnection extends PersistentConnection { this.log.debug( 'temp key has been bound, exp = %d', - inner.expiresAt + inner.expiresAt, ) this._isPfsBindingPending = false @@ -494,6 +496,7 @@ export class SessionConnection extends PersistentConnection { if (this._isPfsBindingPendingInBackground) { this._isPfsBindingPendingInBackground = false + // if we are in background, we can just retry return this._authorizePfs(true) } @@ -510,7 +513,7 @@ export class SessionConnection extends PersistentConnection { promise.reject(new Error('Timeout')) this._pendingWaitForUnencrypted = this._pendingWaitForUnencrypted.filter( - (it) => it[0] !== promise + (it) => it[0] !== promise, ) }, timeout) this._pendingWaitForUnencrypted.push([promise, timeoutId]) @@ -528,7 +531,7 @@ export class SessionConnection extends PersistentConnection { promise.resolve(data) } else { this.log.debug( - 'unencrypted message received, but no one is waiting for it' + 'unencrypted message received, but no one is waiting for it', ) } @@ -704,7 +707,7 @@ export class SessionConnection extends PersistentConnection { if (this.params.disableUpdates) { this.log.warn( - 'received updates, but updates are disabled' + 'received updates, but updates are disabled', ) // likely due to some request in the session missing invokeWithoutUpdates // todo: reset session @@ -748,6 +751,7 @@ export class SessionConnection extends PersistentConnection { } const msg = this._session.pendingMessages.get(reqMsgId) + if (!msg) { let result @@ -783,6 +787,7 @@ export class SessionConnection extends PersistentConnection { if (msg._ !== 'rpc') { if (msg._ === 'bind') { msg.promise.resolve(result) + return } @@ -831,6 +836,7 @@ export class SessionConnection extends PersistentConnection { // (for god's sake why is this not in mtproto and instead hacked into the app layer) this._authorizePfs() this._onMessageFailed(reqMsgId, 'AUTH_KEY_PERM_EMPTY', true) + return } @@ -846,15 +852,16 @@ export class SessionConnection extends PersistentConnection { this.sendRpc({ _: 'help.getNearestDc' }) .then(() => { this.log.debug( - 'additional help.getNearestDc for initConnection ok' + 'additional help.getNearestDc for initConnection ok', ) }) .catch((err) => { this.log.debug( 'additional help.getNearestDc for initConnection error: %s', - err + err, ) }) + return } @@ -938,6 +945,7 @@ export class SessionConnection extends PersistentConnection { } case 'bind': break // do nothing, wait for the result + default: if (!inContainer) { this.log.warn( @@ -980,6 +988,7 @@ export class SessionConnection extends PersistentConnection { inContainer = false, ): void { const msgInfo = this._session.pendingMessages.get(msgId) + if (!msgInfo) { this.log.debug( 'unknown message %l failed because of %s', @@ -1069,7 +1078,7 @@ export class SessionConnection extends PersistentConnection { this.log.debug( 'temp key binding request %l failed because of %s, retrying', msgId, - reason + reason, ) msgInfo.promise.reject(Error(reason)) } @@ -1089,6 +1098,7 @@ export class SessionConnection extends PersistentConnection { private _registerOutgoingMsgId(msgId: Long): Long { this._session.recentOutgoingMsgIds.add(msgId) + return msgId } @@ -1182,7 +1192,7 @@ export class SessionConnection extends PersistentConnection { this.log.error( 'received bad_msg_notification for msg_id = %l, code = %d. session will be reset', msg.badMsgId, - msg.errorCode + msg.errorCode, ) this._resetSession() break @@ -1258,6 +1268,7 @@ export class SessionConnection extends PersistentConnection { ): void { if (!msgId.isZero()) { const info = this._session.pendingMessages.get(msgId) + if (!info) { this.log.info( 'received message info about unknown message %l', @@ -1357,14 +1368,16 @@ export class SessionConnection extends PersistentConnection { private _onDestroySessionResult(msg: mtp.TypeDestroySessionRes): void { const reqMsgId = this._session.destroySessionIdToMsgId.get( - msg.sessionId + msg.sessionId, ) + if (!reqMsgId) { this.log.warn( 'received %s for unknown session %h', msg._, - msg.sessionId + msg.sessionId, ) + return } @@ -1374,8 +1387,7 @@ export class SessionConnection extends PersistentConnection { } private _enqueueRpc(rpc: PendingRpc, force?: boolean) { - if (this._session.enqueueRpc(rpc, force)) - this._flushTimer.emitWhenIdle() + if (this._session.enqueueRpc(rpc, force)) { this._flushTimer.emitWhenIdle() } } _resetSession(): void { @@ -1598,7 +1610,7 @@ export class SessionConnection extends PersistentConnection { private _doFlush(): void { this.log.debug( 'flushing send queue. queued rpc: %d', - this._session.queuedRpc.length + this._session.queuedRpc.length, ) // oh bloody hell mate @@ -1633,6 +1645,7 @@ export class SessionConnection extends PersistentConnection { if (this._session.queuedAcks.length) { let acks = this._session.queuedAcks + if (acks.length > 8192) { this._session.queuedAcks = acks.slice(8192) acks = acks.slice(0, 8192) @@ -1678,6 +1691,7 @@ export class SessionConnection extends PersistentConnection { { if (this._session.queuedStateReq.length) { let ids = this._session.queuedStateReq + if (ids.length > 8192) { this._session.queuedStateReq = ids.slice(8192) ids = ids.slice(0, 8192) @@ -1695,7 +1709,7 @@ export class SessionConnection extends PersistentConnection { if (idx > 0) { const toGetState = this._session.getStateSchedule.raw.splice( 0, - idx + idx, ) if (!getStateMsgIds) getStateMsgIds = [] toGetState.forEach((it) => getStateMsgIds!.push(it.msgId!)) @@ -1718,6 +1732,7 @@ export class SessionConnection extends PersistentConnection { if (this._session.queuedResendReq.length) { resendMsgIds = this._session.queuedResendReq + if (resendMsgIds.length > 8192) { this._session.queuedResendReq = resendMsgIds.slice(8192) resendMsgIds = resendMsgIds.slice(0, 8192) @@ -2008,8 +2023,7 @@ export class SessionConnection extends PersistentConnection { ) // put acks in the front so they are the first to be sent - if (ackMsgIds) - this._session.queuedAcks.splice(0, 0, ...ackMsgIds) + if (ackMsgIds) { this._session.queuedAcks.splice(0, 0, ...ackMsgIds) } this._onMessageFailed(rootMsgId, 'unknown error') }) } diff --git a/packages/core/src/storage/memory.ts b/packages/core/src/storage/memory.ts index a367c51f..27dbff58 100644 --- a/packages/core/src/storage/memory.ts +++ b/packages/core/src/storage/memory.ts @@ -195,7 +195,7 @@ export class MemoryStorage implements ITelegramStorage, IStateStorage { dcId: number, index: number, key: Buffer | null, - expiresAt: number + expiresAt: number, ): void { const k = `${dcId}:${index}` this._state.authKeysTemp[k] = key @@ -210,8 +210,8 @@ export class MemoryStorage implements ITelegramStorage, IStateStorage { if (tempIndex !== undefined) { const k = `${dcId}:${tempIndex}` - if (Date.now() > (this._state.authKeysTempExpiry[k] ?? 0)) - return null + if (Date.now() > (this._state.authKeysTempExpiry[k] ?? 0)) { return null } + return this._state.authKeysTemp[k] } diff --git a/packages/core/src/utils/logger.ts b/packages/core/src/utils/logger.ts index ebec9d14..3907d5f2 100644 --- a/packages/core/src/utils/logger.ts +++ b/packages/core/src/utils/logger.ts @@ -73,7 +73,13 @@ export class Logger { const val = args[idx] args.splice(idx, 1) - if (m === '%h') return Buffer.isBuffer(val) ? val.toString('hex') : val.toString(16) + + if (m === '%h') { + if (Buffer.isBuffer(val)) return val.toString('hex') + if (typeof val === 'number') return val.toString(16) + + return String(val) + } if (m === '%b') return String(Boolean(val)) if (m === '%j') { diff --git a/packages/core/src/utils/long-utils.ts b/packages/core/src/utils/long-utils.ts index afe09fe1..5e603bbd 100644 --- a/packages/core/src/utils/long-utils.ts +++ b/packages/core/src/utils/long-utils.ts @@ -26,9 +26,9 @@ export function randomLong(unsigned = false): Long { export function longFromBuffer(buf: Buffer, unsigned = false, le = true): Long { if (le) { return new Long(buf.readInt32LE(0), buf.readInt32LE(4), unsigned) - } else { - return new Long(buf.readInt32BE(4), buf.readInt32BE(0), unsigned) } + + return new Long(buf.readInt32BE(4), buf.readInt32BE(0), unsigned) } /** diff --git a/packages/sqlite/index.ts b/packages/sqlite/index.ts index 5bd88a19..ee005e5a 100644 --- a/packages/sqlite/index.ts +++ b/packages/sqlite/index.ts @@ -501,15 +501,16 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { return this._getFromKv('def_dc') } - getAuthKeyFor(dcId: number, tempIndex?: number): Promise { + getAuthKeyFor(dcId: number, tempIndex?: number): Buffer | null { let row + if (tempIndex !== undefined) { row = this._statements.getAuthTemp.get(dcId, tempIndex, Date.now()) } else { row = this._statements.getAuth.get(dcId) } - return row ? row.key : null + return row ? (row as { key: Buffer }).key : null } setAuthKeyFor(dcId: number, key: Buffer | null): void { @@ -523,12 +524,12 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { dcId: number, index: number, key: Buffer | null, - expires: number + expires: number, ): void { this._pending.push([ - key === null - ? this._statements.delAuthTemp - : this._statements.setAuthTemp, + key === null ? + this._statements.delAuthTemp : + this._statements.setAuthTemp, key === null ? [dcId, index] : [dcId, index, key, expires], ]) } @@ -536,7 +537,7 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { dropAuthKeysFor(dcId: number): void { this._pending.push( [this._statements.delAuth, [dcId]], - [this._statements.delAllAuthTemp, [dcId]] + [this._statements.delAllAuthTemp, [dcId]], ) }