import { FloodWaitError, RPCError } from '../../../lib/gramjs/errors'; import type { RegularLangKey } from '../../../types/language'; import type { RegularLangFnParameters } from '../../../util/localization'; import type { ApiUpdateAuthorizationState, ApiUpdateAuthorizationStateType, ApiUser, ApiUserFullInfo, } from '../../types'; import { DEBUG } from '../../../config'; import { sendApiUpdate } from '../updates/apiUpdateEmitter'; const ApiErrors: Record = { PHONE_NUMBER_INVALID: 'ErrorPhoneNumberInvalid', PHONE_CODE_INVALID: 'ErrorCodeInvalid', PASSWORD_HASH_INVALID: 'ErrorIncorrectPassword', PHONE_PASSWORD_FLOOD: 'ErrorPasswordFlood', PHONE_NUMBER_BANNED: 'ErrorPhoneBanned', }; const authController: { resolve?: Function; reject?: Function; } = {}; export function onWebAuthTokenFailed() { sendApiUpdate({ '@type': 'updateWebAuthTokenFailed', }); } export function onRequestPhoneNumber() { sendApiUpdate(buildAuthStateUpdate('authorizationStateWaitPhoneNumber')); return new Promise((resolve, reject) => { authController.resolve = resolve; authController.reject = reject; }); } export function onRequestCode(isCodeViaApp = false) { sendApiUpdate({ ...buildAuthStateUpdate('authorizationStateWaitCode'), isCodeViaApp, }); return new Promise((resolve, reject) => { authController.resolve = resolve; authController.reject = reject; }); } export function onRequestPassword(hint?: string, noReset?: boolean) { sendApiUpdate({ ...buildAuthStateUpdate('authorizationStateWaitPassword'), hint, noReset, }); return new Promise((resolve) => { authController.resolve = resolve; }); } export function onRequestRegistration() { sendApiUpdate(buildAuthStateUpdate('authorizationStateWaitRegistration')); return new Promise<[string, string?]>((resolve) => { authController.resolve = resolve; }); } export function onRequestQrCode(qrCode: { token: Buffer; expires: number }) { sendApiUpdate({ ...buildAuthStateUpdate('authorizationStateWaitQrCode'), qrCode: { token: btoa(String.fromCharCode(...qrCode.token)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''), expires: qrCode.expires, }, }); return new Promise((resolve, reject) => { authController.reject = reject; }); } export function onAuthError(err: Error) { let messageKey: RegularLangFnParameters | undefined; if (err instanceof FloodWaitError) { const hours = Math.ceil(Number(err.seconds) / 60 / 60); messageKey = { key: 'ErrorFlood', variables: { hour: hours }, options: { pluralValue: hours }, }; } else if (err instanceof RPCError) { messageKey = { key: ApiErrors[err.errorMessage], }; } else if (err.message) { messageKey = { key: 'ErrorUnexpectedMessage', variables: { error: err.message }, }; } if (!messageKey) { messageKey = { key: 'ErrorUnexpected', }; if (DEBUG) { // eslint-disable-next-line no-console console.error(err); } } sendApiUpdate({ '@type': 'updateAuthorizationError', errorKey: messageKey, }); } export function onAuthReady() { sendApiUpdate(buildAuthStateUpdate('authorizationStateReady')); } export function onCurrentUserUpdate(currentUser: ApiUser, currentUserFullInfo: ApiUserFullInfo) { sendApiUpdate({ '@type': 'updateCurrentUser', currentUser, currentUserFullInfo, }); } export function buildAuthStateUpdate(authorizationState: ApiUpdateAuthorizationStateType): ApiUpdateAuthorizationState { return { '@type': 'updateAuthorizationState', authorizationState, }; } export function provideAuthPhoneNumber(phoneNumber: string) { if (!authController.resolve) { return; } authController.resolve(phoneNumber); } export function provideAuthCode(code: string) { if (!authController.resolve) { return; } authController.resolve(code); } export function provideAuthPassword(password: string) { if (!authController.resolve) { return; } authController.resolve(password); } export function provideAuthRegistration(registration: { firstName: string; lastName: string }) { const { firstName, lastName } = registration; if (!authController.resolve) { return; } authController.resolve([firstName, lastName]); } export function restartAuth() { if (!authController.reject) { return; } authController.reject(new Error('RESTART_AUTH')); } export function restartAuthWithQr() { if (!authController.reject) { return; } authController.reject(new Error('RESTART_AUTH_WITH_QR')); }