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