GramJS: Rework error handling (#6891)
This commit is contained in:
parent
230e9797d4
commit
e5b932b8ea
@ -2,6 +2,7 @@ import { Api as GramJs, errors } from '../../../lib/gramjs';
|
||||
|
||||
import type { RegularLangKey } from '../../../types/language';
|
||||
import type { RegularLangFnParameters } from '../../../util/localization';
|
||||
import type { ApiError } from '../../types';
|
||||
|
||||
import { DEBUG } from '../../../config';
|
||||
import {
|
||||
@ -39,6 +40,10 @@ const ERROR_KEYS: Record<string, RegularLangKey> = {
|
||||
PASSKEY_CREDENTIAL_NOT_FOUND: 'ErrorPasskeyUnknown',
|
||||
};
|
||||
|
||||
function resolveErrorKey(errorMessage: string) {
|
||||
return ERROR_KEYS[errorMessage] || ERROR_KEYS[errorMessage.replace(/_\d+$/, '')];
|
||||
}
|
||||
|
||||
export type MessageRepairContext = Pick<GramJs.TypeMessage, 'peerId' | 'id'>;
|
||||
export type MediaRepairContext = MessageRepairContext;
|
||||
|
||||
@ -102,6 +107,20 @@ export function checkErrorType(error: unknown): error is Error {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function buildApiError(error: Error): Pick<ApiError, 'message' | 'code' | 'hasErrorKey'> {
|
||||
if (error instanceof errors.RPCError) {
|
||||
return {
|
||||
message: error.errorMessage,
|
||||
code: error.code,
|
||||
hasErrorKey: true,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
message: error.message,
|
||||
};
|
||||
}
|
||||
|
||||
export function wrapError<T extends Error>(error: T): WrappedError<T> {
|
||||
let messageKey: RegularLangFnParameters | undefined;
|
||||
|
||||
@ -123,9 +142,12 @@ export function wrapError<T extends Error>(error: T): WrappedError<T> {
|
||||
variables: { time: formatWait(error.seconds) },
|
||||
};
|
||||
} else if (error instanceof errors.RPCError) {
|
||||
messageKey = {
|
||||
key: ERROR_KEYS[error.errorMessage],
|
||||
};
|
||||
const key = resolveErrorKey(error.errorMessage);
|
||||
if (key) {
|
||||
messageKey = {
|
||||
key,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (!messageKey) {
|
||||
|
||||
@ -82,7 +82,9 @@ import {
|
||||
import {
|
||||
addPhotoToLocalDb,
|
||||
} from '../helpers/localDb';
|
||||
import { checkErrorType, isChatFolder, wrapError } from '../helpers/misc';
|
||||
import {
|
||||
buildApiError, checkErrorType, isChatFolder, wrapError,
|
||||
} from '../helpers/misc';
|
||||
import { scheduleMutedChatUpdate } from '../scheduleUnmute';
|
||||
import { sendApiUpdate } from '../updates/apiUpdateEmitter';
|
||||
import {
|
||||
@ -1676,12 +1678,10 @@ export async function addChatMembers(chat: ApiChat, users: ApiUser[]) {
|
||||
return addChatUsersResult.flat().filter(Boolean);
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
const message = err instanceof RPCError ? err.errorMessage : (err as Error).message;
|
||||
const apiError = buildApiError(err as Error);
|
||||
sendApiUpdate({
|
||||
'@type': 'error',
|
||||
error: {
|
||||
message,
|
||||
},
|
||||
error: apiError,
|
||||
});
|
||||
}
|
||||
return undefined;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {
|
||||
Api as GramJs,
|
||||
errors,
|
||||
sessions,
|
||||
type Update,
|
||||
} from '../../../lib/gramjs';
|
||||
@ -40,6 +41,7 @@ import {
|
||||
addWebPageMediaToLocalDb,
|
||||
} from '../helpers/localDb';
|
||||
import {
|
||||
buildApiError,
|
||||
isResponseUpdate, log,
|
||||
} from '../helpers/misc';
|
||||
import localDb, { clearLocalDb, type RepairInfo } from '../localDb';
|
||||
@ -451,9 +453,9 @@ export async function fetchCurrentUser() {
|
||||
}
|
||||
|
||||
export function dispatchErrorUpdate<T extends GramJs.AnyRequest>(err: Error, request: T) {
|
||||
const message = err instanceof RPCError ? err.errorMessage : err.message;
|
||||
const { message, code } = buildApiError(err);
|
||||
|
||||
const isSlowMode = message === 'FLOOD' && (
|
||||
const isSlowMode = err instanceof errors.FloodError && (
|
||||
request instanceof GramJs.messages.SendMessage
|
||||
|| request instanceof GramJs.messages.SendMedia
|
||||
|| request instanceof GramJs.messages.SendMultiMedia
|
||||
@ -463,6 +465,7 @@ export function dispatchErrorUpdate<T extends GramJs.AnyRequest>(err: Error, req
|
||||
'@type': 'error',
|
||||
error: {
|
||||
message,
|
||||
code,
|
||||
isSlowMode,
|
||||
hasErrorKey: true,
|
||||
},
|
||||
|
||||
@ -109,6 +109,7 @@ import {
|
||||
getEntityTypeById,
|
||||
} from '../gramjsBuilders';
|
||||
import {
|
||||
buildApiError,
|
||||
deserializeBytes,
|
||||
resolveMessageApiChatId,
|
||||
} from '../helpers/misc';
|
||||
@ -237,7 +238,7 @@ export async function fetchMessage({ chat, messageId }: { chat: ApiChat; message
|
||||
},
|
||||
);
|
||||
} catch (err: any) {
|
||||
const { message } = err;
|
||||
const { message, code } = buildApiError(err);
|
||||
|
||||
// When fetching messages for the bot @replies, there may be situations when the user was banned
|
||||
// in the comment group or this group was deleted
|
||||
@ -246,6 +247,7 @@ export async function fetchMessage({ chat, messageId }: { chat: ApiChat; message
|
||||
'@type': 'error',
|
||||
error: {
|
||||
message,
|
||||
code,
|
||||
isSlowMode: false,
|
||||
hasErrorKey: true,
|
||||
},
|
||||
@ -821,12 +823,12 @@ export async function editMessage({
|
||||
console.warn(err);
|
||||
}
|
||||
|
||||
const { message: messageErr } = err as Error;
|
||||
const apiError = buildApiError(err as Error);
|
||||
|
||||
sendApiUpdate({
|
||||
'@type': 'error',
|
||||
error: {
|
||||
message: messageErr,
|
||||
...apiError,
|
||||
hasErrorKey: true,
|
||||
},
|
||||
});
|
||||
@ -887,12 +889,12 @@ export async function editTodo({
|
||||
console.warn(err);
|
||||
}
|
||||
|
||||
const { message: messageErr } = err as Error;
|
||||
const apiError = buildApiError(err as Error);
|
||||
|
||||
sendApiUpdate({
|
||||
'@type': 'error',
|
||||
error: {
|
||||
message: messageErr,
|
||||
...apiError,
|
||||
hasErrorKey: true,
|
||||
},
|
||||
});
|
||||
@ -936,12 +938,12 @@ export async function appendTodoList({
|
||||
console.warn(err);
|
||||
}
|
||||
|
||||
const { message: messageErr } = err as Error;
|
||||
const apiError = buildApiError(err as Error);
|
||||
|
||||
sendApiUpdate({
|
||||
'@type': 'error',
|
||||
error: {
|
||||
message: messageErr,
|
||||
...apiError,
|
||||
hasErrorKey: true,
|
||||
},
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { Api } from '../../../lib/gramjs';
|
||||
import type { TypedBroadcastChannel } from '../../../util/browser/multitab';
|
||||
import type { ApiInitialArgs, ApiOnProgress, OnApiUpdate } from '../../types';
|
||||
import type { ApiError, ApiInitialArgs, ApiOnProgress, OnApiUpdate } from '../../types';
|
||||
import type { LocalDb } from '../localDb';
|
||||
import type { MethodArgs, MethodResponse, Methods } from '../methods/types';
|
||||
import type { OriginPayload, ThenArg, WorkerMessageEvent } from './types';
|
||||
@ -313,7 +313,7 @@ function subscribeToWorker(onUpdate: OnApiUpdate) {
|
||||
export function handleMethodResponse(data: {
|
||||
messageId: string;
|
||||
response?: ThenArg<MethodResponse<keyof Methods>>;
|
||||
error?: { message: string };
|
||||
error?: Pick<ApiError, 'message' | 'code' | 'hasErrorKey'>;
|
||||
}) {
|
||||
const requestState = requestStates.get(data.messageId);
|
||||
if (requestState) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { DebugLevel } from '../../../util/debugConsole';
|
||||
import type {
|
||||
ApiInitialArgs, ApiUpdate,
|
||||
ApiError, ApiInitialArgs, ApiUpdate,
|
||||
} from '../../types';
|
||||
import type { LocalDb } from '../localDb';
|
||||
import type { MethodArgs, MethodResponse, Methods } from '../methods/types';
|
||||
@ -17,7 +17,7 @@ export type WorkerPayload =
|
||||
type: 'methodResponse';
|
||||
messageId: string;
|
||||
response?: ThenArg<MethodResponse<keyof Methods>>;
|
||||
error?: { message: string };
|
||||
error?: Pick<ApiError, 'message' | 'code' | 'hasErrorKey'>;
|
||||
}
|
||||
|
|
||||
{
|
||||
|
||||
@ -7,7 +7,7 @@ import type { OriginMessageEvent, WorkerPayload } from './types';
|
||||
import { DEBUG } from '../../../config';
|
||||
import { DEBUG_LEVELS } from '../../../util/debugConsole';
|
||||
import { throttleWithTickEnd } from '../../../util/schedulers';
|
||||
import { log } from '../helpers/misc';
|
||||
import { buildApiError, log } from '../helpers/misc';
|
||||
import { callApi, cancelApiProgress, initApi } from '../methods/init';
|
||||
|
||||
declare const self: WorkerGlobalScope;
|
||||
@ -110,7 +110,7 @@ onmessage = ({ data }: OriginMessageEvent) => {
|
||||
sendToOrigin({
|
||||
type: 'methodResponse',
|
||||
messageId,
|
||||
error: { message: error.message },
|
||||
error: buildApiError(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,6 +174,7 @@ export type ApiDialog = ApiDialogError | ApiDialogMessage | ApiDialogContact | A
|
||||
|
||||
export type ApiError = {
|
||||
message: string;
|
||||
code?: number;
|
||||
entities?: ApiMessageEntity[];
|
||||
hasErrorKey?: boolean;
|
||||
isSlowMode?: boolean;
|
||||
|
||||
@ -12,7 +12,7 @@ import { IS_WAVE_TRANSFORM_SUPPORTED } from '../../../util/browser/windowEnviron
|
||||
import { getAllMultitabTokens, getCurrentTabId, reestablishMasterToSelf } from '../../../util/establishMultitabRole';
|
||||
import { getAllNotificationsCount } from '../../../util/folderManager';
|
||||
import getIsAppUpdateNeeded from '../../../util/getIsAppUpdateNeeded';
|
||||
import getReadableErrorText from '../../../util/getReadableErrorText';
|
||||
import { shouldShowErrorDialog } from '../../../util/getReadableErrorText';
|
||||
import { compact, unique } from '../../../util/iteratees';
|
||||
import { refreshFromCache } from '../../../util/localization';
|
||||
import * as langProvider from '../../../util/oldLangProvider';
|
||||
@ -388,7 +388,7 @@ addActionHandler('showDialog', (global, actions, payload): ActionReturnType => {
|
||||
const { data, tabId = getCurrentTabId() } = payload;
|
||||
|
||||
// Filter out errors that we don't want to show to the user
|
||||
if (data.type === 'error' && data.hasErrorKey && !getReadableErrorText(data)) {
|
||||
if (data.type === 'error' && !shouldShowErrorDialog(data)) {
|
||||
return global;
|
||||
}
|
||||
|
||||
|
||||
@ -4,14 +4,14 @@ import type { Api } from '../tl';
|
||||
* Base class for all Remote Procedure Call errors.
|
||||
*/
|
||||
export class RPCError extends Error {
|
||||
public code: number | undefined;
|
||||
public code: number;
|
||||
|
||||
public errorMessage: string;
|
||||
|
||||
constructor(message: string, request: Api.AnyRequest, code?: number) {
|
||||
constructor(message: string, request: Api.AnyRequest, code: number) {
|
||||
super(
|
||||
'RPCError {0}: {1}{2}'
|
||||
.replace('{0}', code?.toString() || '')
|
||||
.replace('{0}', code.toString())
|
||||
.replace('{1}', message)
|
||||
.replace('{2}', RPCError._fmtRequest(request)),
|
||||
);
|
||||
@ -32,63 +32,37 @@ export class RPCError extends Error {
|
||||
/**
|
||||
* The request must be repeated, but directed to a different data center.
|
||||
*/
|
||||
export class InvalidDCError extends RPCError {
|
||||
constructor(message: string, request: Api.AnyRequest, code?: number) {
|
||||
super(message, request, code);
|
||||
this.code = code || 303;
|
||||
this.errorMessage = message || 'ERROR_SEE_OTHER';
|
||||
}
|
||||
}
|
||||
export class InvalidDCError extends RPCError {}
|
||||
|
||||
/**
|
||||
* The query contains errors. In the event that a request was created
|
||||
* using a form and contains user generated data, the user should be
|
||||
* notified that the data must be corrected before the query is repeated.
|
||||
*/
|
||||
export class BadRequestError extends RPCError {
|
||||
code = 400;
|
||||
|
||||
errorMessage = 'BAD_REQUEST';
|
||||
}
|
||||
export class BadRequestError extends RPCError {}
|
||||
|
||||
/**
|
||||
* There was an unauthorized attempt to use functionality available only
|
||||
* to authorized users.
|
||||
*/
|
||||
export class UnauthorizedError extends RPCError {
|
||||
code = 401;
|
||||
|
||||
errorMessage = 'UNAUTHORIZED';
|
||||
}
|
||||
export class UnauthorizedError extends RPCError {}
|
||||
|
||||
/**
|
||||
* Privacy violation. For example, an attempt to write a message to
|
||||
* someone who has blacklisted the current user.
|
||||
*/
|
||||
export class ForbiddenError extends RPCError {
|
||||
code = 403;
|
||||
|
||||
errorMessage = 'FORBIDDEN';
|
||||
}
|
||||
export class ForbiddenError extends RPCError {}
|
||||
|
||||
/**
|
||||
* An attempt to invoke a non-existent object, such as a method.
|
||||
*/
|
||||
export class NotFoundError extends RPCError {
|
||||
code = 404;
|
||||
|
||||
errorMessage = 'NOT_FOUND';
|
||||
}
|
||||
export class NotFoundError extends RPCError {}
|
||||
|
||||
/**
|
||||
* Errors related to invalid authorization key, like
|
||||
* AUTH_KEY_DUPLICATED which can cause the connection to fail.
|
||||
*/
|
||||
export class AuthKeyError extends RPCError {
|
||||
code = 406;
|
||||
|
||||
errorMessage = 'AUTH_KEY';
|
||||
}
|
||||
export class AuthKeyError extends RPCError {}
|
||||
|
||||
/**
|
||||
* The maximum allowed number of attempts to invoke the given method
|
||||
@ -96,29 +70,21 @@ export class AuthKeyError extends RPCError {
|
||||
* attempt to request a large number of text messages (SMS) for the same
|
||||
* phone number.
|
||||
*/
|
||||
export class FloodError extends RPCError {
|
||||
code = 420;
|
||||
|
||||
errorMessage = 'FLOOD';
|
||||
}
|
||||
export class FloodError extends RPCError {}
|
||||
|
||||
/**
|
||||
* An internal server error occurred while a request was being processed
|
||||
* for example, there was a disruption while accessing a database or file
|
||||
* storage
|
||||
*/
|
||||
export class ServerError extends RPCError {
|
||||
code = 500; // Also witnessed as -500
|
||||
|
||||
errorMessage = 'INTERNAL';
|
||||
}
|
||||
export class ServerError extends RPCError {}
|
||||
|
||||
/**
|
||||
* Clicking the inline buttons of bots that never (or take to long to)
|
||||
* call ``answerCallbackQuery`` will result in this "special" RPCError.
|
||||
*/
|
||||
export class TimedOutError extends RPCError {
|
||||
code = 503; // Only witnessed as -503
|
||||
|
||||
errorMessage = 'Timeout';
|
||||
constructor(args: { request: Api.AnyRequest; code: number }) {
|
||||
super('Timeout', args.request, args.code); // Only witnessed as -503
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @stylistic/max-len */
|
||||
import {
|
||||
BadRequestError, FloodError, InvalidDCError, RPCError, TimedOutError,
|
||||
} from './RPCBaseErrors';
|
||||
@ -8,8 +7,7 @@ export class UserMigrateError extends InvalidDCError {
|
||||
|
||||
constructor(args: any) {
|
||||
const newDc = Number(args.capture || 0);
|
||||
super(`The user whose identity is being used to execute queries is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`, args.request);
|
||||
this.message = `The user whose identity is being used to execute queries is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`;
|
||||
super(args.errorMessage, args.request, args.code);
|
||||
this.newDc = newDc;
|
||||
}
|
||||
}
|
||||
@ -19,8 +17,7 @@ export class PhoneMigrateError extends InvalidDCError {
|
||||
|
||||
constructor(args: any) {
|
||||
const newDc = Number(args.capture || 0);
|
||||
super(`The phone number a user is trying to use for authorization is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`, args.request);
|
||||
this.message = `The phone number a user is trying to use for authorization is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`;
|
||||
super(args.errorMessage, args.request, args.code);
|
||||
this.newDc = newDc;
|
||||
}
|
||||
}
|
||||
@ -30,11 +27,7 @@ export class SlowModeWaitError extends FloodError {
|
||||
|
||||
constructor(args: any) {
|
||||
const seconds = Number(args.capture || 0);
|
||||
super(
|
||||
`A wait of ${seconds} seconds is required before sending another message in this chat ${RPCError._fmtRequest(args.request)}`,
|
||||
args.request,
|
||||
);
|
||||
this.message = `A wait of ${seconds} seconds is required before sending another message in this chat${RPCError._fmtRequest(args.request)}`;
|
||||
super(args.errorMessage, args.request, args.code);
|
||||
this.seconds = seconds;
|
||||
}
|
||||
}
|
||||
@ -44,11 +37,7 @@ export class FloodWaitError extends FloodError {
|
||||
|
||||
constructor(args: any) {
|
||||
const seconds = Number(args.capture || 0);
|
||||
super(
|
||||
`A wait of ${seconds} seconds is required${RPCError._fmtRequest(args.request)}`,
|
||||
args.request,
|
||||
);
|
||||
this.message = `A wait of ${seconds} seconds is required${RPCError._fmtRequest(args.request)}`;
|
||||
super(args.errorMessage, args.request, args.code);
|
||||
this.seconds = seconds;
|
||||
}
|
||||
}
|
||||
@ -56,21 +45,14 @@ export class FloodWaitError extends FloodError {
|
||||
export class FloodPremiumWaitError extends FloodWaitError {
|
||||
constructor(args: any) {
|
||||
const seconds = Number(args.capture || 0);
|
||||
super(`A wait of ${seconds} seconds is required${RPCError._fmtRequest(args.request)}`);
|
||||
this.message = `A wait of ${seconds} seconds is required${RPCError._fmtRequest(args.request)}`;
|
||||
super(args);
|
||||
this.seconds = seconds;
|
||||
}
|
||||
}
|
||||
|
||||
export class MsgWaitError extends FloodError {
|
||||
constructor(args: any) {
|
||||
super(
|
||||
`Message failed to be sent.${RPCError._fmtRequest(args.request)}`,
|
||||
args.request,
|
||||
);
|
||||
this.message = `Message failed to be sent.${RPCError._fmtRequest(
|
||||
args.request,
|
||||
)}`;
|
||||
super(args.errorMessage, args.request, args.code);
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,11 +61,7 @@ export class FloodTestPhoneWaitError extends FloodError {
|
||||
|
||||
constructor(args: any) {
|
||||
const seconds = Number(args.capture || 0);
|
||||
super(
|
||||
`A wait of ${seconds} seconds is required in the test servers${RPCError._fmtRequest(args.request)}`,
|
||||
args.request,
|
||||
);
|
||||
this.message = `A wait of ${seconds} seconds is required in the test servers${RPCError._fmtRequest(args.request)}`;
|
||||
super(args.errorMessage, args.request, args.code);
|
||||
this.seconds = seconds;
|
||||
}
|
||||
}
|
||||
@ -93,11 +71,7 @@ export class FileMigrateError extends InvalidDCError {
|
||||
|
||||
constructor(args: any) {
|
||||
const newDc = Number(args.capture || 0);
|
||||
super(
|
||||
`The file to be accessed is currently stored in DC ${newDc}${RPCError._fmtRequest(args.request)}`,
|
||||
args.request,
|
||||
);
|
||||
this.message = `The file to be accessed is currently stored in DC ${newDc}${RPCError._fmtRequest(args.request)}`;
|
||||
super(args.errorMessage, args.request, args.code);
|
||||
this.newDc = newDc;
|
||||
}
|
||||
}
|
||||
@ -107,11 +81,7 @@ export class NetworkMigrateError extends InvalidDCError {
|
||||
|
||||
constructor(args: any) {
|
||||
const newDc = Number(args.capture || 0);
|
||||
super(
|
||||
`The source IP address is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`,
|
||||
args.request,
|
||||
);
|
||||
this.message = `The source IP address is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`;
|
||||
super(args.errorMessage, args.request, args.code);
|
||||
this.newDc = newDc;
|
||||
}
|
||||
}
|
||||
@ -121,17 +91,7 @@ export class EmailUnconfirmedError extends BadRequestError {
|
||||
|
||||
constructor(args: any) {
|
||||
const codeLength = Number(args.capture || 0);
|
||||
super(
|
||||
`Email unconfirmed, the length of the code must be ${codeLength}${RPCError._fmtRequest(
|
||||
args.request,
|
||||
)}`,
|
||||
args.request,
|
||||
400,
|
||||
);
|
||||
|
||||
this.message = `Email unconfirmed, the length of the code must be ${codeLength}${RPCError._fmtRequest(
|
||||
args.request,
|
||||
)}`;
|
||||
super(args.errorMessage, args.request, args.code);
|
||||
this.codeLength = codeLength;
|
||||
}
|
||||
}
|
||||
@ -141,9 +101,7 @@ export class PasswordFreshError extends BadRequestError {
|
||||
|
||||
constructor(args: any) {
|
||||
const seconds = Number(args.capture || 0);
|
||||
super(`The password was modified less than 24 hours ago, try again in ${seconds} seconds.`, args.request);
|
||||
|
||||
this.message = `The password was modified less than 24 hours ago, try again in ${seconds} seconds.`;
|
||||
super(args.errorMessage, args.request, args.code);
|
||||
this.seconds = seconds;
|
||||
}
|
||||
}
|
||||
@ -153,9 +111,7 @@ export class SessionFreshError extends BadRequestError {
|
||||
|
||||
constructor(args: any) {
|
||||
const seconds = Number(args.capture || 0);
|
||||
super(`Session is fresh, please try again in ${seconds} seconds.`, args.request);
|
||||
|
||||
this.message = `Session is fresh, please try again in ${seconds} seconds.`;
|
||||
super(args.errorMessage, args.request, args.code);
|
||||
this.seconds = seconds;
|
||||
}
|
||||
}
|
||||
@ -181,7 +137,7 @@ export class UserAlreadyAuthorizedError extends Error {
|
||||
|
||||
export class PasskeyCredentialNotFoundError extends RPCError {
|
||||
constructor(args: any) {
|
||||
super('PASSKEY_CREDENTIAL_NOT_FOUND', args.request);
|
||||
super(args.errorMessage, args.request, args.code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,12 @@ export function RPCMessageToError(
|
||||
const m = rpcError.errorMessage.match(msgRegex);
|
||||
if (m) {
|
||||
const capture = m.length === 2 ? parseInt(m[1], 10) : undefined;
|
||||
return new Cls({ request, capture });
|
||||
return new Cls({
|
||||
request,
|
||||
capture,
|
||||
code: rpcError.errorCode,
|
||||
errorMessage: rpcError.errorMessage,
|
||||
});
|
||||
}
|
||||
}
|
||||
return new RPCError(rpcError.errorMessage, request, rpcError.errorCode);
|
||||
|
||||
@ -136,6 +136,10 @@ const FINAL_PAYMENT_ERRORS = new Set([
|
||||
'PAYMENT_FAILED',
|
||||
]);
|
||||
|
||||
const ERROR_CODES_WITHOUT_DIALOG = new Set([
|
||||
406,
|
||||
]);
|
||||
|
||||
export default function getReadableErrorText(error: ApiError) {
|
||||
const { message, isSlowMode, textParams } = error;
|
||||
// Currently, Telegram API doesn't return `SLOWMODE_WAIT_X` error as described in the docs
|
||||
@ -159,3 +163,10 @@ export function getShippingError(error: ApiError): ApiFieldError | undefined {
|
||||
export function shouldClosePaymentModal(error: ApiError): boolean {
|
||||
return FINAL_PAYMENT_ERRORS.has(error.message);
|
||||
}
|
||||
|
||||
export function shouldShowErrorDialog(error: ApiError): boolean {
|
||||
if (error.code && ERROR_CODES_WITHOUT_DIALOG.has(error.code)) return false;
|
||||
if (error.hasErrorKey && !getReadableErrorText(error)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user