diff --git a/packages/core/src/base-client.ts b/packages/core/src/base-client.ts index baaa75d6..86ea28ba 100644 --- a/packages/core/src/base-client.ts +++ b/packages/core/src/base-client.ts @@ -7,16 +7,15 @@ import { __tlReaderMap as defaultReaderMap } from '@mtcute/tl/binary/reader.js' import { __tlWriterMap as defaultWriterMap } from '@mtcute/tl/binary/writer.js' import { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime' +import { BaseTelegramClientOptions } from './base-client.types.js' import { ConfigManager } from './network/config-manager.js' -import { ReconnectionStrategy, SessionConnection, TransportFactory } from './network/index.js' -import { NetworkManager, NetworkManagerExtraParams, RpcCallOptions } from './network/network-manager.js' -import { PersistentConnectionParams } from './network/persistent-connection.js' +import { SessionConnection, TransportFactory } from './network/index.js' +import { NetworkManager, RpcCallOptions } from './network/network-manager.js' import { ITelegramStorage } from './storage/index.js' import { MustEqual } from './types/index.js' import { ControllablePromise, createControllablePromise, - CryptoProviderFactory, defaultCryptoProviderFactory, defaultProductionDc, defaultProductionIpv6Dc, @@ -26,176 +25,11 @@ import { ICryptoProvider, LogManager, readStringSession, + StringSessionData, toggleChannelIdMark, writeStringSession, } from './utils/index.js' -/** Options for {@link BaseTelegramClient} */ -export interface BaseTelegramClientOptions { - /** - * API ID from my.telegram.org - */ - apiId: number | string - /** - * API hash from my.telegram.org - */ - apiHash: string - - /** - * Storage to use for this client. - */ - storage: ITelegramStorage - - /** - * Cryptography provider factory to allow delegating - * crypto to native addon, worker, etc. - */ - crypto?: CryptoProviderFactory - - /** - * Whether to use IPv6 datacenters - * (IPv6 will be preferred when choosing a DC by id) - * (default: false) - */ - useIpv6?: boolean - - /** - * Primary DC to use for initial connection. - * This does not mean this will be the only DC used, - * nor that this DC will actually be primary, this only - * determines the first DC the library will try to connect to. - * Can be used to connect to other networks (like test DCs). - * - * When session already contains primary DC, this parameter is ignored. - * - * @default Production DC 2. - */ - defaultDcs?: ITelegramStorage.DcOptions - - /** - * Whether to connect to test servers. - * - * If passed, {@link defaultDc} defaults to Test DC 2. - * - * **Must** be passed if using test servers, even if - * you passed custom {@link defaultDc} - */ - testMode?: boolean - - /** - * Additional options for initConnection call. - * `apiId` and `query` are not available and will be ignored. - * Omitted values will be filled with defaults - */ - initConnectionOptions?: Partial> - - /** - * Transport factory to use in the client. - * - * @default platform-specific transport: WebSocket on the web, TCP in node - */ - transport?: TransportFactory - - /** - * Reconnection strategy. - * - * @default simple reconnection strategy: first 0ms, then up to 5s (increasing by 1s) - */ - reconnectionStrategy?: ReconnectionStrategy - - /** - * Maximum duration of a flood_wait that will be waited automatically. - * Flood waits above this threshold will throw a FloodWaitError. - * Set to 0 to disable. Can be overridden with `throwFlood` parameter in call() params - * - * @default 10000 - */ - floodSleepThreshold?: number - - /** - * Maximum number of retries when calling RPC methods. - * Call is retried when InternalError or FloodWaitError is encountered. - * Can be set to Infinity. - * - * @default 5 - */ - maxRetryCount?: number - - /** - * If true, every single API call will be wrapped with `tl.invokeWithoutUpdates`, - * effectively disabling the server-sent events for the clients. - * May be useful in some cases. - * - * Note that this only wraps calls made with `.call()` within the primary - * connection. Additional connections and direct `.sendForResult()` calls - * must be wrapped manually. - * - * @default false - */ - disableUpdates?: boolean - - /** - * mtcute can send all unknown RPC errors to [danog](https://github.com/danog)'s - * [error reporting service](https://rpc.pwrtelegram.xyz/). - * - * This is fully anonymous (except maybe IP) and is only used to improve the library - * and developer experience for everyone working with MTProto. This is fully opt-in, - * and if you're too paranoid, you can disable it by manually passing `enableErrorReporting: false` to the client. - * - * @default false - */ - enableErrorReporting?: boolean - - /** - * If true, RPC errors will have a stack trace of the initial `.call()` - * or `.sendForResult()` call position, which drastically improves - * debugging experience.
- * If false, they will have a stack trace of mtcute internals. - * - * Internally this creates a stack capture before every RPC call - * and stores it until the result is received. This might - * use a lot more memory than normal, thus can be disabled here. - * - * @default true - */ - niceStacks?: boolean - - /** - * Extra parameters for {@link NetworkManager} - */ - network?: NetworkManagerExtraParams - - /** - * Set logging level for the client. - * - * See static members of {@link LogManager} for possible values. - */ - logLevel?: number - - /** - * **EXPERT USE ONLY!** - * - * Override TL layer used for the connection. - * - * **Does not** change the schema used. - */ - overrideLayer?: number - - /** - * **EXPERT USE ONLY** - * - * Override reader map used for the connection. - */ - readerMap?: TlReaderMap - - /** - * **EXPERT USE ONLY** - * - * Override writer map used for the connection. - */ - writerMap?: TlWriterMap -} - /** * Basic Telegram client that only implements the bare minimum * to make RPC calls and receive low-level updates. @@ -248,9 +82,9 @@ export class BaseTelegramClient extends EventEmitter { // not really connected, but rather "connect() was called" private _connected: ControllablePromise | boolean = false - private _onError?: (err: unknown, connection?: SessionConnection) => void + _emitError: (err: unknown, connection?: SessionConnection) => void = console.error.bind(console) - private _importFrom?: string + private _importFrom?: StringSessionData private _importForce?: boolean readonly log = new LogManager('client') @@ -372,7 +206,7 @@ export class BaseTelegramClient extends EventEmitter { const defaultDcAuthKey = await this.storage.getAuthKeyFor(this._defaultDcs.main.id) if ((this._importForce || !defaultDcAuthKey) && this._importFrom) { - const data = readStringSession(this._readerMap, this._importFrom) + const data = this._importFrom if (data.testMode !== this._testMode) { throw new Error( @@ -517,7 +351,7 @@ export class BaseTelegramClient extends EventEmitter { * this was connection-related error. */ onError(handler: (err: unknown, connection?: SessionConnection) => void): void { - this._onError = handler + this._emitError = handler } notifyLoggedIn(auth: tl.auth.RawAuthorization): void { @@ -525,15 +359,9 @@ export class BaseTelegramClient extends EventEmitter { this.emit('logged_in', auth) } - _emitError(err: unknown, connection?: SessionConnection): void { - if (this._onError) { - this._onError(err, connection) - } else { - console.error(err) - } - } - /** + * **ADVANCED** + * * Adds all peers from a given object to entity cache in storage. */ async _cachePeersFrom(obj: object): Promise { @@ -634,18 +462,18 @@ export class BaseTelegramClient extends EventEmitter { /** * Request the session to be imported from the given session string. * - * Note that the string will not be parsed and imported right away, - * instead, it will be imported when `connect()` is called + * Note that the session will not be imported right away, + * instead, it will be imported once `connect()` is called * * Also note that the session will only be imported in case * the storage is missing authorization (i.e. does not contain - * auth key for the primary DC), otherwise it will be ignored (unless `force). + * auth key for the primary DC), otherwise it will be ignored (unless `force`). * * @param session Session string to import * @param force Whether to overwrite existing session */ - importSession(session: string, force = false): void { - this._importFrom = session + importSession(session: string | StringSessionData, force = false): void { + this._importFrom = typeof session === 'string' ? readStringSession(this._readerMap, session) : session this._importForce = force } } diff --git a/packages/core/src/base-client.types.ts b/packages/core/src/base-client.types.ts new file mode 100644 index 00000000..e42b8334 --- /dev/null +++ b/packages/core/src/base-client.types.ts @@ -0,0 +1,173 @@ +import { tl } from '@mtcute/tl' +import { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime' + +import { NetworkManagerExtraParams, ReconnectionStrategy, TransportFactory } from './network/index.js' +import { PersistentConnectionParams } from './network/persistent-connection.js' +import { ITelegramStorage } from './storage/abstract.js' +import { CryptoProviderFactory } from './utils/index.js' + +/** Options for {@link BaseTelegramClient} */ +export interface BaseTelegramClientOptions { + /** + * API ID from my.telegram.org + */ + apiId: number | string + /** + * API hash from my.telegram.org + */ + apiHash: string + + /** + * Storage to use for this client. + */ + storage: ITelegramStorage + + /** + * Cryptography provider factory to allow delegating + * crypto to native addon, worker, etc. + */ + crypto?: CryptoProviderFactory + + /** + * Whether to use IPv6 datacenters + * (IPv6 will be preferred when choosing a DC by id) + * (default: false) + */ + useIpv6?: boolean + + /** + * Primary DC to use for initial connection. + * This does not mean this will be the only DC used, + * nor that this DC will actually be primary, this only + * determines the first DC the library will try to connect to. + * Can be used to connect to other networks (like test DCs). + * + * When session already contains primary DC, this parameter is ignored. + * + * @default Production DC 2. + */ + defaultDcs?: ITelegramStorage.DcOptions + + /** + * Whether to connect to test servers. + * + * If passed, {@link defaultDc} defaults to Test DC 2. + * + * **Must** be passed if using test servers, even if + * you passed custom {@link defaultDc} + */ + testMode?: boolean + + /** + * Additional options for initConnection call. + * `apiId` and `query` are not available and will be ignored. + * Omitted values will be filled with defaults + */ + initConnectionOptions?: Partial> + + /** + * Transport factory to use in the client. + * + * @default platform-specific transport: WebSocket on the web, TCP in node + */ + transport?: TransportFactory + + /** + * Reconnection strategy. + * + * @default simple reconnection strategy: first 0ms, then up to 5s (increasing by 1s) + */ + reconnectionStrategy?: ReconnectionStrategy + + /** + * Maximum duration of a flood_wait that will be waited automatically. + * Flood waits above this threshold will throw a FloodWaitError. + * Set to 0 to disable. Can be overridden with `throwFlood` parameter in call() params + * + * @default 10000 + */ + floodSleepThreshold?: number + + /** + * Maximum number of retries when calling RPC methods. + * Call is retried when InternalError or FloodWaitError is encountered. + * Can be set to Infinity. + * + * @default 5 + */ + maxRetryCount?: number + + /** + * If true, every single API call will be wrapped with `tl.invokeWithoutUpdates`, + * effectively disabling the server-sent events for the clients. + * May be useful in some cases. + * + * Note that this only wraps calls made with `.call()` within the primary + * connection. Additional connections and direct `.sendForResult()` calls + * must be wrapped manually. + * + * @default false + */ + disableUpdates?: boolean + + /** + * mtcute can send all unknown RPC errors to [danog](https://github.com/danog)'s + * [error reporting service](https://rpc.pwrtelegram.xyz/). + * + * This is fully anonymous (except maybe IP) and is only used to improve the library + * and developer experience for everyone working with MTProto. This is fully opt-in, + * and if you're too paranoid, you can disable it by manually passing `enableErrorReporting: false` to the client. + * + * @default false + */ + enableErrorReporting?: boolean + + /** + * If true, RPC errors will have a stack trace of the initial `.call()` + * or `.sendForResult()` call position, which drastically improves + * debugging experience.
+ * If false, they will have a stack trace of mtcute internals. + * + * Internally this creates a stack capture before every RPC call + * and stores it until the result is received. This might + * use a lot more memory than normal, thus can be disabled here. + * + * @default true + */ + niceStacks?: boolean + + /** + * Extra parameters for {@link NetworkManager} + */ + network?: NetworkManagerExtraParams + + /** + * Set logging level for the client. + * + * See static members of {@link LogManager} for possible values. + */ + logLevel?: number + + /** + * **EXPERT USE ONLY!** + * + * Override TL layer used for the connection. + * + * **Does not** change the schema used. + */ + overrideLayer?: number + + /** + * **EXPERT USE ONLY** + * + * Override reader map used for the connection. + */ + readerMap?: TlReaderMap + + /** + * **EXPERT USE ONLY** + * + * Override writer map used for the connection. + */ + writerMap?: TlWriterMap +} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 565e3747..a5a1e4fe 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,4 +1,5 @@ export * from './base-client.js' +export * from './base-client.types.js' export * from './network/index.js' export * from './storage/index.js' export * from './types/index.js'