Compare commits

..

No commits in common. "9a79f8d3d0f3c4bb69feb96308c3a0816766680d" and "4e810072543211cab141d81d03cc1aa7d72fb40d" have entirely different histories.

7 changed files with 39 additions and 60 deletions

View file

@ -70,13 +70,6 @@ export class BaseTelegramClient implements ITelegramClient {
this.mt = new MtClient({ this.mt = new MtClient({
...this.params, ...this.params,
logger: this.log.create('mtproto'), logger: this.log.create('mtproto'),
onError: (err) => {
if (this.onError.length > 0) {
this.onError.emit(unknownToError(err))
} else if (this._connect.finished()) {
this.log.error('unhandled error:', err)
}
},
}) })
if (!params.disableUpdates && params.updates !== false) { if (!params.disableUpdates && params.updates !== false) {

View file

@ -393,20 +393,11 @@ export interface TelegramClient extends ITelegramClient {
* *
* **Available**: 👤 users only * **Available**: 👤 users only
* *
* @param password Your Two-Step verification password
* @returns The authorized user * @returns The authorized user
* @throws BadRequestError In case the password is invalid * @throws BadRequestError In case the password is invalid
*/ */
checkPassword( checkPassword(password: string): Promise<User>
options: string | {
/** Your Two-Step verification password */
password: string
/** Existing response from `account.getPassword`, if available (to avoid extra API calls) */
passwordObj?: tl.account.TypePassword
/** Abort signal */
abortSignal?: AbortSignal
}): Promise<User>
/** /**
* Get your Two-Step Verification password hint. * Get your Two-Step Verification password hint.
* *
@ -4552,15 +4543,13 @@ export interface TelegramClient extends ITelegramClient {
* @returns Whether the action was successful * @returns Whether the action was successful
*/ */
acceptStarGift( acceptStarGift(
params: { params: InputMessageId & {
/** ID of the message containing the gift */ /**
message: number | Message * Action to perform on the gift.
/** * - `save` - save the gift to your profile
* Action to perform on the gift. * - `hide` - hide the gift from your profile
* - `save` - save the gift to your profile * - `convert` - convert the gift to stars (can't be undone)
* - `hide` - hide the gift from your profile */
* - `convert` - convert the gift to stars (can't be undone)
*/
action: 'save' | 'hide' | 'convert' action: 'save' | 'hide' | 'convert'
}): Promise<boolean> }): Promise<boolean>
/** /**

View file

@ -1,4 +1,3 @@
import type { tl } from '@mtcute/tl'
import type { ITelegramClient } from '../../client.types.js' import type { ITelegramClient } from '../../client.types.js'
import type { User } from '../../types/index.js' import type { User } from '../../types/index.js'
@ -7,34 +6,20 @@ import { _onAuthorization } from './utils.js'
/** /**
* Check your Two-Step verification password and log in * Check your Two-Step verification password and log in
* *
* @param password Your Two-Step verification password
* @returns The authorized user * @returns The authorized user
* @throws BadRequestError In case the password is invalid * @throws BadRequestError In case the password is invalid
*/ */
export async function checkPassword( export async function checkPassword(client: ITelegramClient, password: string): Promise<User> {
client: ITelegramClient,
options: string | {
/** Your Two-Step verification password */
password: string
/** Existing response from `account.getPassword`, if available (to avoid extra API calls) */
passwordObj?: tl.account.TypePassword
/** Abort signal */
abortSignal?: AbortSignal
},
): Promise<User> {
const opts = typeof options === 'string' ? { password: options } : options
const passwordObj = opts.passwordObj ?? await client.call({
_: 'account.getPassword',
}, { abortSignal: opts.abortSignal })
const res = await client.call({ const res = await client.call({
_: 'auth.checkPassword', _: 'auth.checkPassword',
password: await client.computeSrpParams( password: await client.computeSrpParams(
passwordObj, await client.call({
opts.password, _: 'account.getPassword',
}),
password,
), ),
}, { abortSignal: opts.abortSignal }) })
return _onAuthorization(client, res) return _onAuthorization(client, res)
} }

View file

@ -76,10 +76,7 @@ export async function signInQr(
const password = await resolveMaybeDynamic(input) const password = await resolveMaybeDynamic(input)
try { try {
return await checkPassword(client, { return await checkPassword(client, password)
password,
abortSignal,
})
} catch (e) { } catch (e) {
if (tl.RpcError.is(e, 'PASSWORD_HASH_INVALID')) { if (tl.RpcError.is(e, 'PASSWORD_HASH_INVALID')) {
if (!isDynamic) { if (!isDynamic) {

View file

@ -266,10 +266,7 @@ export async function start(
const password = await resolveMaybeDynamic(params.password) const password = await resolveMaybeDynamic(params.password)
try { try {
return await checkPassword(client, { return await checkPassword(client, password)
password,
abortSignal,
})
} catch (e) { } catch (e) {
if (typeof params.password !== 'function') { if (typeof params.password !== 'function') {
throw new MtArgumentError('Provided password was invalid') throw new MtArgumentError('Provided password was invalid')

View file

@ -213,6 +213,8 @@ export class MtClient {
return res return res
}) })
private _emitError?: (err: unknown) => void
readonly log: Logger readonly log: Logger
readonly network: NetworkManager readonly network: NetworkManager
@ -224,7 +226,7 @@ export class MtClient {
readonly onNetworkChanged: Emitter<boolean> = new Emitter() readonly onNetworkChanged: Emitter<boolean> = new Emitter()
readonly onUpdate: Emitter<tl.TypeUpdates> = new Emitter() readonly onUpdate: Emitter<tl.TypeUpdates> = new Emitter()
constructor(readonly params: MtClientOptions & { onError: (err: unknown) => void }) { constructor(readonly params: MtClientOptions) {
this.log = params.logger ?? new LogManager(undefined, params.platform) this.log = params.logger ?? new LogManager(undefined, params.platform)
if (params.logLevel !== undefined) { if (params.logLevel !== undefined) {
@ -276,7 +278,7 @@ export class MtClient {
storage: this.storage, storage: this.storage,
testMode: Boolean(params.testMode), testMode: Boolean(params.testMode),
transport: params.transport, transport: params.transport,
emitError: params.onError, emitError: this.emitError.bind(this),
isPremium: false, isPremium: false,
useIpv6: Boolean(params.useIpv6), useIpv6: Boolean(params.useIpv6),
enableErrorReporting: params.enableErrorReporting ?? false, enableErrorReporting: params.enableErrorReporting ?? false,
@ -292,6 +294,14 @@ export class MtClient {
) )
} }
emitError(err: unknown): void {
if (this._emitError) {
this._emitError(err)
} else if (this._connect.finished()) {
this.log.error('unhandled error:', err)
}
}
private _prepare = asyncResettable(async () => { private _prepare = asyncResettable(async () => {
await this.crypto.initialize?.() await this.crypto.initialize?.()
await this.storage.load() await this.storage.load()
@ -365,4 +375,13 @@ export class MtClient {
): Promise<tl.RpcCallReturn[T['_']] | mtp.RawMt_rpc_error> { ): Promise<tl.RpcCallReturn[T['_']] | mtp.RawMt_rpc_error> {
return this.network.call(message, params) return this.network.call(message, params)
} }
/**
* Register an error handler for the client
*
* @param handler Error handler.
*/
onError(handler: (err: unknown) => void): void {
this._emitError = handler
}
} }

View file

@ -275,7 +275,6 @@ export class SessionConnection extends PersistentConnection {
// there happened a little trolling // there happened a little trolling
this.log.warn('transport error 404, reauthorizing') this.log.warn('transport error 404, reauthorizing')
this.onError.emit(error)
this._session.resetAuthKey() this._session.resetAuthKey()
this._resetSession() this._resetSession()
this.onKeyChange.emit(null) this.onKeyChange.emit(null)