diff --git a/packages/client/src/methods/auth/accept-tos.ts b/packages/client/src/methods/auth/accept-tos.ts index ed65931e..67763985 100644 --- a/packages/client/src/methods/auth/accept-tos.ts +++ b/packages/client/src/methods/auth/accept-tos.ts @@ -1,5 +1,6 @@ +import { MtTypeAssertionError } from '@mtcute/core' + import { TelegramClient } from '../../client' -import { MtTypeAssertionError } from '../../types' /** * Accept the given TOS diff --git a/packages/client/src/methods/auth/check-password.ts b/packages/client/src/methods/auth/check-password.ts index e382dd0c..813c0760 100644 --- a/packages/client/src/methods/auth/check-password.ts +++ b/packages/client/src/methods/auth/check-password.ts @@ -1,8 +1,7 @@ -import { computeSrpParams } from '@mtcute/core/utils' +import { assertTypeIs, computeSrpParams } from '@mtcute/core/utils' import { TelegramClient } from '../../client' import { User } from '../../types' -import { assertTypeIs } from '../../utils/type-assertion' /** * Check your Two-Step verification password and log in diff --git a/packages/client/src/methods/auth/recover-password.ts b/packages/client/src/methods/auth/recover-password.ts index be3a4d33..631126a2 100644 --- a/packages/client/src/methods/auth/recover-password.ts +++ b/packages/client/src/methods/auth/recover-password.ts @@ -1,6 +1,7 @@ +import { assertTypeIs } from '@mtcute/core/utils' + import { TelegramClient } from '../../client' import { User } from '../../types' -import { assertTypeIs } from '../../utils/type-assertion' /** * Recover your password with a recovery code and log in. diff --git a/packages/client/src/methods/auth/resend-code.ts b/packages/client/src/methods/auth/resend-code.ts index c7c2f9ff..05c17f11 100644 --- a/packages/client/src/methods/auth/resend-code.ts +++ b/packages/client/src/methods/auth/resend-code.ts @@ -1,7 +1,8 @@ +import { assertTypeIs } from '@mtcute/core/utils' + import { TelegramClient } from '../../client' import { SentCode } from '../../types' import { normalizePhoneNumber } from '../../utils/misc-utils' -import { assertTypeIs } from '../../utils/type-assertion' /** * Re-send the confirmation code using a different type. diff --git a/packages/client/src/methods/auth/send-code.ts b/packages/client/src/methods/auth/send-code.ts index 88548b87..772b30ac 100644 --- a/packages/client/src/methods/auth/send-code.ts +++ b/packages/client/src/methods/auth/send-code.ts @@ -1,7 +1,8 @@ +import { assertTypeIs } from '@mtcute/core/utils' + import { TelegramClient } from '../../client' import { SentCode } from '../../types' import { normalizePhoneNumber } from '../../utils/misc-utils' -import { assertTypeIs } from '../../utils/type-assertion' /** * Send the confirmation code to the given phone number diff --git a/packages/client/src/methods/auth/sign-in-bot.ts b/packages/client/src/methods/auth/sign-in-bot.ts index a7a49ea2..02289366 100644 --- a/packages/client/src/methods/auth/sign-in-bot.ts +++ b/packages/client/src/methods/auth/sign-in-bot.ts @@ -1,6 +1,7 @@ +import { assertTypeIs } from '@mtcute/core/utils' + import { TelegramClient } from '../../client' import { User } from '../../types' -import { assertTypeIs } from '../../utils/type-assertion' /** * Authorize a bot using its token issued by [@BotFather](//t.me/BotFather) diff --git a/packages/client/src/methods/auth/sign-in.ts b/packages/client/src/methods/auth/sign-in.ts index d37afd6c..34a68dd5 100644 --- a/packages/client/src/methods/auth/sign-in.ts +++ b/packages/client/src/methods/auth/sign-in.ts @@ -1,7 +1,8 @@ +import { assertTypeIs } from '@mtcute/core/utils' + import { TelegramClient } from '../../client' import { TermsOfService, User } from '../../types' import { normalizePhoneNumber } from '../../utils/misc-utils' -import { assertTypeIs } from '../../utils/type-assertion' /** * Authorize a user in Telegram with a valid confirmation code. diff --git a/packages/client/src/methods/auth/sign-up.ts b/packages/client/src/methods/auth/sign-up.ts index b9449e2c..f6c63cb5 100644 --- a/packages/client/src/methods/auth/sign-up.ts +++ b/packages/client/src/methods/auth/sign-up.ts @@ -1,7 +1,8 @@ +import { assertTypeIs } from '@mtcute/core/utils' + import { TelegramClient } from '../../client' import { User } from '../../types' import { normalizePhoneNumber } from '../../utils/misc-utils' -import { assertTypeIs } from '../../utils/type-assertion' /** * Register a new user in Telegram. diff --git a/packages/client/src/methods/auth/start-test.ts b/packages/client/src/methods/auth/start-test.ts index 19ab6b5a..37248ccf 100644 --- a/packages/client/src/methods/auth/start-test.ts +++ b/packages/client/src/methods/auth/start-test.ts @@ -1,5 +1,7 @@ +import { MtArgumentError } from '@mtcute/core' + import { TelegramClient } from '../../client' -import { MaybeDynamic, MtArgumentError, User } from '../../types' +import { MaybeDynamic, User } from '../../types' /** * Utility function to quickly authorize on test DC diff --git a/packages/client/src/methods/auth/start.ts b/packages/client/src/methods/auth/start.ts index a1a70568..d1370284 100644 --- a/packages/client/src/methods/auth/start.ts +++ b/packages/client/src/methods/auth/start.ts @@ -1,11 +1,11 @@ /* eslint-disable no-console */ +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { MaybeAsync, MaybeDynamic, - MtArgumentError, SentCode, TermsOfService, User, diff --git a/packages/client/src/methods/chats/ban-chat-member.ts b/packages/client/src/methods/chats/ban-chat-member.ts index 7b66c8b8..0a005c37 100644 --- a/packages/client/src/methods/chats/ban-chat-member.ts +++ b/packages/client/src/methods/chats/ban-chat-member.ts @@ -1,10 +1,7 @@ +import { MtTypeAssertionError } from '@mtcute/core' + import { TelegramClient } from '../../client' -import { - InputPeerLike, - Message, - MtInvalidPeerTypeError, - MtTypeAssertionError, -} from '../../types' +import { InputPeerLike, Message, MtInvalidPeerTypeError } from '../../types' import { isInputPeerChannel, isInputPeerChat, diff --git a/packages/client/src/methods/chats/get-chat-member.ts b/packages/client/src/methods/chats/get-chat-member.ts index 1fd09e55..62680e85 100644 --- a/packages/client/src/methods/chats/get-chat-member.ts +++ b/packages/client/src/methods/chats/get-chat-member.ts @@ -1,3 +1,4 @@ +import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' @@ -13,7 +14,6 @@ import { isInputPeerUser, normalizeToInputChannel, } from '../../utils/peer-utils' -import { assertTypeIs } from '../../utils/type-assertion' /** * Get information about a single chat member diff --git a/packages/client/src/methods/chats/get-chat-members.ts b/packages/client/src/methods/chats/get-chat-members.ts index 4948bf07..1d4180ac 100644 --- a/packages/client/src/methods/chats/get-chat-members.ts +++ b/packages/client/src/methods/chats/get-chat-members.ts @@ -1,20 +1,22 @@ import Long from 'long' import { assertNever } from '@mtcute/core' +import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { - ArrayWithTotal, ChatMember, + ArrayWithTotal, + ChatMember, InputPeerLike, MtInvalidPeerTypeError, - PeersIndex } from '../../types' + PeersIndex, +} from '../../types' import { isInputPeerChannel, isInputPeerChat, normalizeToInputChannel, } from '../../utils/peer-utils' -import { assertTypeIs } from '../../utils/type-assertion' /** * Get a chunk of members of some chat. diff --git a/packages/client/src/methods/chats/get-chat-preview.ts b/packages/client/src/methods/chats/get-chat-preview.ts index c7215e11..52a9cdfc 100644 --- a/packages/client/src/methods/chats/get-chat-preview.ts +++ b/packages/client/src/methods/chats/get-chat-preview.ts @@ -1,5 +1,7 @@ +import { MtArgumentError } from '@mtcute/core' + import { TelegramClient } from '../../client' -import { ChatPreview, MtArgumentError, MtPeerNotFoundError } from '../../types' +import { ChatPreview, MtPeerNotFoundError } from '../../types' import { INVITE_LINK_REGEX } from '../../utils/peer-utils' /** diff --git a/packages/client/src/methods/chats/get-chat.ts b/packages/client/src/methods/chats/get-chat.ts index 060ba198..7b9896aa 100644 --- a/packages/client/src/methods/chats/get-chat.ts +++ b/packages/client/src/methods/chats/get-chat.ts @@ -1,7 +1,8 @@ +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { Chat, InputPeerLike, MtArgumentError } from '../../types' +import { Chat, InputPeerLike } from '../../types' import { INVITE_LINK_REGEX, isInputPeerChannel, diff --git a/packages/client/src/methods/chats/get-full-chat.ts b/packages/client/src/methods/chats/get-full-chat.ts index 628d4caf..57394bea 100644 --- a/packages/client/src/methods/chats/get-full-chat.ts +++ b/packages/client/src/methods/chats/get-full-chat.ts @@ -1,7 +1,8 @@ +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { Chat, InputPeerLike, MtArgumentError } from '../../types' +import { Chat, InputPeerLike } from '../../types' import { INVITE_LINK_REGEX, isInputPeerChannel, diff --git a/packages/client/src/methods/chats/get-nearby-chats.ts b/packages/client/src/methods/chats/get-nearby-chats.ts index 399a6cb5..99ba9538 100644 --- a/packages/client/src/methods/chats/get-nearby-chats.ts +++ b/packages/client/src/methods/chats/get-nearby-chats.ts @@ -1,9 +1,9 @@ import { getMarkedPeerId } from '@mtcute/core' +import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { Chat } from '../../types' -import { assertTypeIs } from '../../utils/type-assertion' import { assertIsUpdatesGroup } from '../../utils/updates-utils' /** diff --git a/packages/client/src/methods/chats/set-chat-photo.ts b/packages/client/src/methods/chats/set-chat-photo.ts index fb023b1b..e9122aab 100644 --- a/packages/client/src/methods/chats/set-chat-photo.ts +++ b/packages/client/src/methods/chats/set-chat-photo.ts @@ -1,3 +1,4 @@ +import { MtArgumentError } from '@mtcute/core' import { fileIdToInputPhoto, tdFileId } from '@mtcute/file-id' import { tl } from '@mtcute/tl' @@ -6,7 +7,6 @@ import { InputFileLike, InputPeerLike, isUploadedFile, - MtArgumentError, MtInvalidPeerTypeError, } from '../../types' import { @@ -37,14 +37,18 @@ export async function setChatPhoto( ): Promise { const chat = await this.resolvePeer(chatId) - if (!(isInputPeerChannel(chat) || isInputPeerChat(chat))) { throw new MtInvalidPeerTypeError(chatId, 'chat or channel') } + if (!(isInputPeerChannel(chat) || isInputPeerChat(chat))) { + throw new MtInvalidPeerTypeError(chatId, 'chat or channel') + } let photo: tl.TypeInputChatPhoto | undefined = undefined let inputFile: tl.TypeInputFile if (tdFileId.isFileIdLike(media)) { - if (typeof media === 'string' && media.match(/^https?:\/\//)) { throw new MtArgumentError("Chat photo can't be external") } + if (typeof media === 'string' && media.match(/^https?:\/\//)) { + throw new MtArgumentError("Chat photo can't be external") + } if (typeof media === 'string' && media.match(/^file:/)) { const uploaded = await this.uploadFile({ file: media.substring(5), diff --git a/packages/client/src/methods/contacts/get-contacts.ts b/packages/client/src/methods/contacts/get-contacts.ts index 6c536fcd..bc1f984e 100644 --- a/packages/client/src/methods/contacts/get-contacts.ts +++ b/packages/client/src/methods/contacts/get-contacts.ts @@ -1,8 +1,9 @@ import Long from 'long' +import { assertTypeIs } from '@mtcute/core/utils' + import { TelegramClient } from '../../client' import { User } from '../../types' -import { assertTypeIs } from '../../utils/type-assertion' /** * Get list of contacts from your Telegram contacts list. diff --git a/packages/client/src/methods/dialogs/edit-folder.ts b/packages/client/src/methods/dialogs/edit-folder.ts index 16637ea8..8697b7fb 100644 --- a/packages/client/src/methods/dialogs/edit-folder.ts +++ b/packages/client/src/methods/dialogs/edit-folder.ts @@ -1,7 +1,7 @@ +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { MtArgumentError } from '../../types' /** * Edit a folder with given modification @@ -31,7 +31,9 @@ export async function editFolder( (it.id === folder || it.title === folder), ) - if (!found) { throw new MtArgumentError(`Could not find a folder ${folder}`) } + if (!found) { + throw new MtArgumentError(`Could not find a folder ${folder}`) + } folder = found as tl.RawDialogFilter } diff --git a/packages/client/src/methods/dialogs/find-folder.ts b/packages/client/src/methods/dialogs/find-folder.ts index 055b31c9..64dade44 100644 --- a/packages/client/src/methods/dialogs/find-folder.ts +++ b/packages/client/src/methods/dialogs/find-folder.ts @@ -1,7 +1,7 @@ +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { MtArgumentError } from '../../types' /** * Find a folder by its parameter. @@ -21,7 +21,9 @@ export async function findFolder( id?: number }, ): Promise { - if (!params.title && !params.emoji && !params.id) { throw new MtArgumentError('One of search parameters must be passed') } + if (!params.title && !params.emoji && !params.id) { + throw new MtArgumentError('One of search parameters must be passed') + } const folders = await this.getFolders() diff --git a/packages/client/src/methods/dialogs/get-dialogs.ts b/packages/client/src/methods/dialogs/get-dialogs.ts index 2565f910..716c76f4 100644 --- a/packages/client/src/methods/dialogs/get-dialogs.ts +++ b/packages/client/src/methods/dialogs/get-dialogs.ts @@ -1,9 +1,10 @@ import Long from 'long' +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { Dialog, MtArgumentError } from '../../types' +import { Dialog } from '../../types' import { normalizeDate } from '../../utils/misc-utils' /** @@ -233,10 +234,11 @@ export async function* getDialogs( } } - const filterFolder = filters ? // if pinned is `only`, this wouldn't be reached + // if pinned is `only`, this wouldn't be reached // if pinned is `exclude`, we want to exclude them // if pinned is `include`, we already yielded them, so we also want to exclude them // if pinned is `keep`, we want to keep them + const filterFolder = filters ? Dialog.filterFolder(filters, pinned !== 'keep') : undefined diff --git a/packages/client/src/methods/dialogs/parse-dialogs.ts b/packages/client/src/methods/dialogs/parse-dialogs.ts index 03cb9f9e..3bce4e9e 100644 --- a/packages/client/src/methods/dialogs/parse-dialogs.ts +++ b/packages/client/src/methods/dialogs/parse-dialogs.ts @@ -1,8 +1,8 @@ -import { getMarkedPeerId } from '@mtcute/core' +import { getMarkedPeerId, MtTypeAssertionError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { Dialog, MtTypeAssertionError, PeersIndex } from '../../types' +import { Dialog, PeersIndex } from '../../types' /** @internal */ export function _parseDialogs( diff --git a/packages/client/src/methods/files/download-file.ts b/packages/client/src/methods/files/download-file.ts index 32b0bd47..111ba576 100644 --- a/packages/client/src/methods/files/download-file.ts +++ b/packages/client/src/methods/files/download-file.ts @@ -1,10 +1,7 @@ -import { TelegramClient } from '../../client' -import { - FileDownloadParameters, - FileLocation, - MtUnsupportedError, -} from '../../types' +import { MtUnsupportedError } from '@mtcute/core' +import { TelegramClient } from '../../client' +import { FileDownloadParameters, FileLocation } from '../../types' let fs: typeof import('fs') | null = null try { diff --git a/packages/client/src/methods/files/download-iterable.ts b/packages/client/src/methods/files/download-iterable.ts index 12e992f4..d4632775 100644 --- a/packages/client/src/methods/files/download-iterable.ts +++ b/packages/client/src/methods/files/download-iterable.ts @@ -1,4 +1,8 @@ -import { ConnectionKind } from '@mtcute/core' +import { + ConnectionKind, + MtArgumentError, + MtUnsupportedError, +} from '@mtcute/core' import { ConditionVariable } from '@mtcute/core/utils' import { fileIdToInputFileLocation, @@ -8,12 +12,7 @@ import { import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - FileDownloadParameters, - FileLocation, - MtArgumentError, - MtUnsupportedError, -} from '../../types' +import { FileDownloadParameters, FileLocation } from '../../types' import { determinePartSize } from '../../utils/file-utils' // small files (less than 128 kb) are downloaded using the "downloadSmall" pool diff --git a/packages/client/src/methods/files/normalize-file-to-document.ts b/packages/client/src/methods/files/normalize-file-to-document.ts index b5205afe..4f1e7ac7 100644 --- a/packages/client/src/methods/files/normalize-file-to-document.ts +++ b/packages/client/src/methods/files/normalize-file-to-document.ts @@ -1,8 +1,8 @@ +import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { InputFileLike } from '../../types' -import { assertTypeIs } from '../../utils/type-assertion' /** * @internal diff --git a/packages/client/src/methods/files/normalize-input-file.ts b/packages/client/src/methods/files/normalize-input-file.ts index 5a146fa7..ce211bb0 100644 --- a/packages/client/src/methods/files/normalize-input-file.ts +++ b/packages/client/src/methods/files/normalize-input-file.ts @@ -1,8 +1,9 @@ +import { MtArgumentError } from '@mtcute/core' import { tdFileId } from '@mtcute/file-id' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { InputFileLike, isUploadedFile, MtArgumentError } from '../../types' +import { InputFileLike, isUploadedFile } from '../../types' /** * Normalize a {@link InputFileLike} to `InputFile`, diff --git a/packages/client/src/methods/files/normalize-input-media.ts b/packages/client/src/methods/files/normalize-input-media.ts index 739d4a77..317a0461 100644 --- a/packages/client/src/methods/files/normalize-input-media.ts +++ b/packages/client/src/methods/files/normalize-input-media.ts @@ -1,5 +1,6 @@ import Long from 'long' +import { assertTypeIs } from '@mtcute/core/utils' import { fileIdToInputDocument, fileIdToInputPhoto, @@ -12,7 +13,6 @@ import { TelegramClient } from '../../client' import { InputMediaLike, isUploadedFile, UploadFileLike } from '../../types' import { extractFileName } from '../../utils/file-utils' import { normalizeDate } from '../../utils/misc-utils' -import { assertTypeIs } from '../../utils/type-assertion' import { encodeWaveform } from '../../utils/voice-utils' /** @@ -267,8 +267,8 @@ export async function _normalizeInputMedia( ) assertTypeIs( 'normalizeInputMedia (@ messages.uploadMedia)', - res.document!, - 'document', + res.document!, + 'document', ) return { @@ -377,7 +377,9 @@ export async function _normalizeInputMedia( roundMessage: media.isRound, }) - if (media.isAnimated) { attributes.push({ _: 'documentAttributeAnimated' }) } + if (media.isAnimated) { + attributes.push({ _: 'documentAttributeAnimated' }) + } } if (media.type === 'audio' || media.type === 'voice') { diff --git a/packages/client/src/methods/files/upload-file.ts b/packages/client/src/methods/files/upload-file.ts index d1ddc1f6..aa5e1cdd 100644 --- a/packages/client/src/methods/files/upload-file.ts +++ b/packages/client/src/methods/files/upload-file.ts @@ -2,11 +2,12 @@ import { fromBuffer as fileTypeFromBuffer } from 'file-type' import type { ReadStream } from 'fs' import { Readable } from 'stream' +import { MtArgumentError } from '@mtcute/core' import { AsyncLock, randomLong } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { MtArgumentError, UploadedFile, UploadFileLike } from '../../types' +import { UploadedFile, UploadFileLike } from '../../types' import { determinePartSize, isProbablyPlainText } from '../../utils/file-utils' import { bufferToStream, diff --git a/packages/client/src/methods/files/upload-media.ts b/packages/client/src/methods/files/upload-media.ts index 0104551a..c6c584da 100644 --- a/packages/client/src/methods/files/upload-media.ts +++ b/packages/client/src/methods/files/upload-media.ts @@ -1,17 +1,19 @@ -import { assertNever } from '@mtcute/core' +import { + assertNever, + MtArgumentError, + MtTypeAssertionError, +} from '@mtcute/core' +import { assertTypeIs } from '@mtcute/core/utils' import { TelegramClient } from '../../client' import { InputMediaLike, InputPeerLike, MessageMedia, - MtArgumentError, - MtTypeAssertionError, Photo, RawDocument, } from '../../types' import { parseDocument } from '../../types/media/document-utils' -import { assertTypeIs } from '../../utils/type-assertion' /** * Upload a media to Telegram servers, without actually diff --git a/packages/client/src/methods/invite-links/get-invite-links.ts b/packages/client/src/methods/invite-links/get-invite-links.ts index 0e16e45d..057084c8 100644 --- a/packages/client/src/methods/invite-links/get-invite-links.ts +++ b/packages/client/src/methods/invite-links/get-invite-links.ts @@ -1,13 +1,8 @@ +import { MtTypeAssertionError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - ChatInviteLink, - InputPeerLike, - MtInvalidPeerTypeError, - MtTypeAssertionError, - PeersIndex, -} from '../../types' +import { ChatInviteLink, InputPeerLike, PeersIndex } from '../../types' import { normalizeToInputUser } from '../../utils/peer-utils' /** diff --git a/packages/client/src/methods/invite-links/get-primary-invite-link.ts b/packages/client/src/methods/invite-links/get-primary-invite-link.ts index 0bbe4191..9b270c6c 100644 --- a/packages/client/src/methods/invite-links/get-primary-invite-link.ts +++ b/packages/client/src/methods/invite-links/get-primary-invite-link.ts @@ -1,10 +1,7 @@ +import { MtTypeAssertionError } from '@mtcute/core' + import { TelegramClient } from '../../client' -import { - ChatInviteLink, - InputPeerLike, - MtTypeAssertionError, - PeersIndex, -} from '../../types' +import { ChatInviteLink, InputPeerLike, PeersIndex } from '../../types' /** * Get primary invite link of a chat diff --git a/packages/client/src/methods/messages/close-poll.ts b/packages/client/src/methods/messages/close-poll.ts index baebcc16..0954454f 100644 --- a/packages/client/src/methods/messages/close-poll.ts +++ b/packages/client/src/methods/messages/close-poll.ts @@ -1,13 +1,10 @@ import Long from 'long' +import { MtTypeAssertionError } from '@mtcute/core' +import { assertTypeIs } from '@mtcute/core/utils' + import { TelegramClient } from '../../client' -import { - InputPeerLike, - MtTypeAssertionError, - PeersIndex, - Poll, -} from '../../types' -import { assertTypeIs } from '../../utils/type-assertion' +import { InputPeerLike, PeersIndex, Poll } from '../../types' import { assertIsUpdatesGroup } from '../../utils/updates-utils' /** diff --git a/packages/client/src/methods/messages/find-in-update.ts b/packages/client/src/methods/messages/find-in-update.ts index b672fc40..b03095ab 100644 --- a/packages/client/src/methods/messages/find-in-update.ts +++ b/packages/client/src/methods/messages/find-in-update.ts @@ -1,7 +1,8 @@ +import { MtTypeAssertionError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { Message, MtTypeAssertionError, PeersIndex } from '../../types' +import { Message, PeersIndex } from '../../types' import { assertIsUpdatesGroup } from '../../utils/updates-utils' /** @internal */ diff --git a/packages/client/src/methods/messages/forward-messages.ts b/packages/client/src/methods/messages/forward-messages.ts index b227485b..747ed467 100644 --- a/packages/client/src/methods/messages/forward-messages.ts +++ b/packages/client/src/methods/messages/forward-messages.ts @@ -1,4 +1,4 @@ -import { MaybeArray } from '@mtcute/core' +import { MaybeArray, MtArgumentError } from '@mtcute/core' import { randomLong } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' @@ -8,7 +8,6 @@ import { InputMediaLike, InputPeerLike, Message, - MtArgumentError, PeersIndex, } from '../../types' import { normalizeDate } from '../../utils/misc-utils' diff --git a/packages/client/src/methods/messages/get-history.ts b/packages/client/src/methods/messages/get-history.ts index 1979b8bc..f92b3f59 100644 --- a/packages/client/src/methods/messages/get-history.ts +++ b/packages/client/src/methods/messages/get-history.ts @@ -1,12 +1,9 @@ import Long from 'long' +import { MtTypeAssertionError } from '@mtcute/core' + import { TelegramClient } from '../../client' -import { - InputPeerLike, - Message, - MtTypeAssertionError, - PeersIndex, -} from '../../types' +import { InputPeerLike, Message, PeersIndex } from '../../types' import { normalizeDate } from '../../utils/misc-utils' /** diff --git a/packages/client/src/methods/messages/get-message-group.ts b/packages/client/src/methods/messages/get-message-group.ts index e379e16d..a2e6ee3f 100644 --- a/packages/client/src/methods/messages/get-message-group.ts +++ b/packages/client/src/methods/messages/get-message-group.ts @@ -1,5 +1,7 @@ +import { MtArgumentError } from '@mtcute/core' + import { TelegramClient } from '../../client' -import { InputPeerLike, Message, MtArgumentError } from '../../types' +import { InputPeerLike, Message } from '../../types' import { isInputPeerChannel } from '../../utils/peer-utils' /** diff --git a/packages/client/src/methods/messages/get-message-reactions.ts b/packages/client/src/methods/messages/get-message-reactions.ts index 26b76f43..fcc74701 100644 --- a/packages/client/src/methods/messages/get-message-reactions.ts +++ b/packages/client/src/methods/messages/get-message-reactions.ts @@ -1,8 +1,8 @@ import { getMarkedPeerId, MaybeArray } from '@mtcute/core' +import { assertTypeIs } from '@mtcute/core/utils' import { TelegramClient } from '../../client' import { InputPeerLike, MessageReactions, PeersIndex } from '../../types' -import { assertTypeIs } from '../../utils/type-assertion' import { assertIsUpdatesGroup } from '../../utils/updates-utils' /** diff --git a/packages/client/src/methods/messages/get-messages-unsafe.ts b/packages/client/src/methods/messages/get-messages-unsafe.ts index 44186efd..dce148b3 100644 --- a/packages/client/src/methods/messages/get-messages-unsafe.ts +++ b/packages/client/src/methods/messages/get-messages-unsafe.ts @@ -1,8 +1,8 @@ -import { MaybeArray } from '@mtcute/core' +import { MaybeArray, MtTypeAssertionError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { Message, MtTypeAssertionError, PeersIndex } from '../../types' +import { Message, PeersIndex } from '../../types' /** * Get a single message from PM or legacy group by its ID. diff --git a/packages/client/src/methods/messages/get-messages.ts b/packages/client/src/methods/messages/get-messages.ts index 0826824c..49bb5ecd 100644 --- a/packages/client/src/methods/messages/get-messages.ts +++ b/packages/client/src/methods/messages/get-messages.ts @@ -1,13 +1,8 @@ -import { MaybeArray } from '@mtcute/core' +import { MaybeArray, MtTypeAssertionError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - InputPeerLike, - Message, - MtTypeAssertionError, - PeersIndex, -} from '../../types' +import { InputPeerLike, Message, PeersIndex } from '../../types' import { isInputPeerChannel, normalizeToInputChannel, @@ -105,7 +100,9 @@ export async function getMessages( msg.peerId._ === 'peerUser' && msg.peerId.userId === this._userId ) - ) { return null } + ) { + return null + } break case 'inputPeerUser': case 'inputPeerUserFromMessage': @@ -114,7 +111,9 @@ export async function getMessages( msg.peerId._ === 'peerUser' && msg.peerId.userId === peer.userId ) - ) { return null } + ) { + return null + } break case 'inputPeerChat': if ( @@ -122,7 +121,9 @@ export async function getMessages( msg.peerId._ === 'peerChat' && msg.peerId.chatId === peer.chatId ) - ) { return null } + ) { + return null + } break } } diff --git a/packages/client/src/methods/messages/get-scheduled-messages.ts b/packages/client/src/methods/messages/get-scheduled-messages.ts index f62fbeb3..2094fc54 100644 --- a/packages/client/src/methods/messages/get-scheduled-messages.ts +++ b/packages/client/src/methods/messages/get-scheduled-messages.ts @@ -1,12 +1,7 @@ -import { MaybeArray } from '@mtcute/core' +import { MaybeArray, MtTypeAssertionError } from '@mtcute/core' import { TelegramClient } from '../../client' -import { - InputPeerLike, - Message, - MtTypeAssertionError, - PeersIndex, -} from '../../types' +import { InputPeerLike, Message, PeersIndex } from '../../types' /** * Get a single scheduled message in chat by its ID diff --git a/packages/client/src/methods/messages/parse-entities.ts b/packages/client/src/methods/messages/parse-entities.ts index 3d8fca67..c7bbe232 100644 --- a/packages/client/src/methods/messages/parse-entities.ts +++ b/packages/client/src/methods/messages/parse-entities.ts @@ -1,8 +1,9 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { FormattedString, MtClientError } from '../../types' +import { FormattedString } from '../../types' import { normalizeToInputUser } from '../../utils/peer-utils' const empty: [string, undefined] = ['', undefined] @@ -33,7 +34,7 @@ export async function _parseEntities( const modeImpl = this._parseModes.get(mode) if (!modeImpl) { - throw new MtClientError(`Parse mode ${mode} is not registered.`) + throw new MtArgumentError(`Parse mode ${mode} is not registered.`) } [text, entities] = modeImpl.parse(text) diff --git a/packages/client/src/methods/messages/search-global.ts b/packages/client/src/methods/messages/search-global.ts index cf5cad66..1e74894d 100644 --- a/packages/client/src/methods/messages/search-global.ts +++ b/packages/client/src/methods/messages/search-global.ts @@ -1,7 +1,8 @@ +import { MtTypeAssertionError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { Message, MtTypeAssertionError, PeersIndex, SearchFilters } from '../../types' +import { Message, PeersIndex, SearchFilters } from '../../types' /** * Search for messages globally from all of your chats diff --git a/packages/client/src/methods/messages/search-messages.ts b/packages/client/src/methods/messages/search-messages.ts index 36c2eff9..01dfbd06 100644 --- a/packages/client/src/methods/messages/search-messages.ts +++ b/packages/client/src/methods/messages/search-messages.ts @@ -1,14 +1,10 @@ import Long from 'long' +import { MtTypeAssertionError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - InputPeerLike, - Message, - MtTypeAssertionError, - PeersIndex, - SearchFilters } from '../../types' +import { InputPeerLike, Message, PeersIndex, SearchFilters } from '../../types' import { normalizeDate } from '../../utils/misc-utils' /** diff --git a/packages/client/src/methods/messages/send-media-group.ts b/packages/client/src/methods/messages/send-media-group.ts index db466410..1ab47520 100644 --- a/packages/client/src/methods/messages/send-media-group.ts +++ b/packages/client/src/methods/messages/send-media-group.ts @@ -1,4 +1,4 @@ -import { getMarkedPeerId } from '@mtcute/core' +import { getMarkedPeerId, MtArgumentError } from '@mtcute/core' import { randomLong } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' @@ -8,7 +8,6 @@ import { InputMediaLike, InputPeerLike, Message, - MtArgumentError, MtMessageNotFoundError, PeersIndex, ReplyMarkup, diff --git a/packages/client/src/methods/messages/send-media.ts b/packages/client/src/methods/messages/send-media.ts index df947aca..d3f05ea3 100644 --- a/packages/client/src/methods/messages/send-media.ts +++ b/packages/client/src/methods/messages/send-media.ts @@ -1,4 +1,4 @@ -import { getMarkedPeerId } from '@mtcute/core' +import { getMarkedPeerId, MtArgumentError } from '@mtcute/core' import { randomLong } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' @@ -9,7 +9,6 @@ import { InputMediaLike, InputPeerLike, Message, - MtArgumentError, MtMessageNotFoundError, ReplyMarkup, } from '../../types' diff --git a/packages/client/src/methods/messages/send-reaction.ts b/packages/client/src/methods/messages/send-reaction.ts index 0d4e7342..0963bf2e 100644 --- a/packages/client/src/methods/messages/send-reaction.ts +++ b/packages/client/src/methods/messages/send-reaction.ts @@ -1,14 +1,10 @@ import Long from 'long' +import { MtTypeAssertionError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - InputPeerLike, - Message, - MtTypeAssertionError, - PeersIndex, -} from '../../types' +import { InputPeerLike, Message, PeersIndex } from '../../types' import { assertIsUpdatesGroup } from '../../utils/updates-utils' /** diff --git a/packages/client/src/methods/messages/send-text.ts b/packages/client/src/methods/messages/send-text.ts index 8b988c45..c1a8b717 100644 --- a/packages/client/src/methods/messages/send-text.ts +++ b/packages/client/src/methods/messages/send-text.ts @@ -1,4 +1,8 @@ -import { getMarkedPeerId } from '@mtcute/core' +import { + getMarkedPeerId, + MtArgumentError, + MtTypeAssertionError, +} from '@mtcute/core' import { randomLong } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' @@ -8,9 +12,7 @@ import { FormattedString, InputPeerLike, Message, - MtArgumentError, MtMessageNotFoundError, - MtTypeAssertionError, PeersIndex, ReplyMarkup, } from '../../types' diff --git a/packages/client/src/methods/messages/send-vote.ts b/packages/client/src/methods/messages/send-vote.ts index 1dbee858..d644b386 100644 --- a/packages/client/src/methods/messages/send-vote.ts +++ b/packages/client/src/methods/messages/send-vote.ts @@ -1,16 +1,19 @@ -import { getMarkedPeerId, MaybeArray } from '@mtcute/core' +import { + getMarkedPeerId, + MaybeArray, + MtArgumentError, + MtTypeAssertionError, +} from '@mtcute/core' +import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { InputPeerLike, - MtArgumentError, MtMessageNotFoundError, - MtTypeAssertionError, PeersIndex, Poll, } from '../../types' -import { assertTypeIs } from '../../utils/type-assertion' import { assertIsUpdatesGroup } from '../../utils/updates-utils' /** diff --git a/packages/client/src/methods/parse-modes/parse-modes.ts b/packages/client/src/methods/parse-modes/parse-modes.ts index df67c4e9..ab95118a 100644 --- a/packages/client/src/methods/parse-modes/parse-modes.ts +++ b/packages/client/src/methods/parse-modes/parse-modes.ts @@ -1,5 +1,7 @@ +import { MtArgumentError } from '@mtcute/core' + import { TelegramClient } from '../../client' -import { IMessageEntityParser, MtClientError } from '../../types' +import { IMessageEntityParser } from '../../types' /** * Register a given {@link IMessageEntityParser} as a parse mode @@ -17,7 +19,7 @@ export function registerParseMode( const name = parseMode.name if (this._parseModes.has(name)) { - throw new MtClientError( + throw new MtArgumentError( `Parse mode ${name} is already registered. Unregister it first!`, ) } @@ -60,7 +62,7 @@ export function getParseMode( ): IMessageEntityParser { if (!name) { if (!this._defaultParseMode) { - throw new MtClientError('There is no default parse mode') + throw new MtArgumentError('There is no default parse mode') } name = this._defaultParseMode @@ -69,7 +71,7 @@ export function getParseMode( const mode = this._parseModes.get(name) if (!mode) { - throw new MtClientError(`Parse mode ${name} is not registered.`) + throw new MtArgumentError(`Parse mode ${name} is not registered.`) } return mode @@ -84,7 +86,7 @@ export function getParseMode( */ export function setDefaultParseMode(this: TelegramClient, name: string): void { if (!this._parseModes.has(name)) { - throw new MtClientError(`Parse mode ${name} is not registered.`) + throw new MtArgumentError(`Parse mode ${name} is not registered.`) } this._defaultParseMode = name diff --git a/packages/client/src/methods/pasword/change-cloud-password.ts b/packages/client/src/methods/pasword/change-cloud-password.ts index cbb18a91..c665c626 100644 --- a/packages/client/src/methods/pasword/change-cloud-password.ts +++ b/packages/client/src/methods/pasword/change-cloud-password.ts @@ -1,8 +1,11 @@ -import { computeNewPasswordHash, computeSrpParams } from '@mtcute/core/utils' +import { MtArgumentError } from '@mtcute/core' +import { + assertTypeIs, + computeNewPasswordHash, + computeSrpParams, +} from '@mtcute/core/utils' import { TelegramClient } from '../../client' -import { MtArgumentError } from '../../types' -import { assertTypeIs } from '../../utils/type-assertion' /** * Change your 2FA password diff --git a/packages/client/src/methods/pasword/enable-cloud-password.ts b/packages/client/src/methods/pasword/enable-cloud-password.ts index 79e84ebc..1c34bcde 100644 --- a/packages/client/src/methods/pasword/enable-cloud-password.ts +++ b/packages/client/src/methods/pasword/enable-cloud-password.ts @@ -1,8 +1,7 @@ -import { computeNewPasswordHash } from '@mtcute/core/utils' +import { MtArgumentError } from '@mtcute/core' +import { assertTypeIs, computeNewPasswordHash } from '@mtcute/core/utils' import { TelegramClient } from '../../client' -import { MtArgumentError } from '../../types' -import { assertTypeIs } from '../../utils/type-assertion' /** * Enable 2FA password on your account diff --git a/packages/client/src/methods/pasword/remove-cloud-password.ts b/packages/client/src/methods/pasword/remove-cloud-password.ts index 350b50c3..843c1791 100644 --- a/packages/client/src/methods/pasword/remove-cloud-password.ts +++ b/packages/client/src/methods/pasword/remove-cloud-password.ts @@ -1,7 +1,7 @@ +import { MtArgumentError } from '@mtcute/core' import { computeSrpParams } from '@mtcute/core/utils' import { TelegramClient } from '../../client' -import { MtArgumentError } from '../../types' /** * Remove 2FA password from your account diff --git a/packages/client/src/methods/stickers/create-sticker-set.ts b/packages/client/src/methods/stickers/create-sticker-set.ts index 34e07f6f..f116fd26 100644 --- a/packages/client/src/methods/stickers/create-sticker-set.ts +++ b/packages/client/src/methods/stickers/create-sticker-set.ts @@ -1,3 +1,4 @@ +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' @@ -5,7 +6,6 @@ import { InputFileLike, InputPeerLike, InputStickerSetItem, - MtArgumentError, StickerSet, StickerSourceType, StickerType, diff --git a/packages/client/src/methods/stickers/get-custom-emojis.ts b/packages/client/src/methods/stickers/get-custom-emojis.ts index bde9ca50..49100fbc 100644 --- a/packages/client/src/methods/stickers/get-custom-emojis.ts +++ b/packages/client/src/methods/stickers/get-custom-emojis.ts @@ -1,9 +1,10 @@ +import { MtTypeAssertionError } from '@mtcute/core' +import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { MtTypeAssertionError, Sticker } from '../../types' +import { Sticker } from '../../types' import { parseDocument } from '../../types/media/document-utils' -import { assertTypeIs } from '../../utils/type-assertion' /** * Get custom emoji stickers by their IDs diff --git a/packages/client/src/methods/stickers/get-installed-stickers.ts b/packages/client/src/methods/stickers/get-installed-stickers.ts index ec00667b..d47c8f25 100644 --- a/packages/client/src/methods/stickers/get-installed-stickers.ts +++ b/packages/client/src/methods/stickers/get-installed-stickers.ts @@ -1,8 +1,9 @@ import Long from 'long' +import { assertTypeIs } from '@mtcute/core/utils' + import { TelegramClient } from '../../client' import { StickerSet } from '../../types' -import { assertTypeIs } from '../../utils/type-assertion' /** * Get a list of all installed sticker packs diff --git a/packages/client/src/methods/updates.ts b/packages/client/src/methods/updates.ts index 0ac9e48c..76b83392 100644 --- a/packages/client/src/methods/updates.ts +++ b/packages/client/src/methods/updates.ts @@ -1,5 +1,5 @@ /* eslint-disable max-depth */ -import { assertNever } from '@mtcute/core' +import { assertNever, MtArgumentError } from '@mtcute/core' import { AsyncLock, ConditionVariable, @@ -14,7 +14,7 @@ import { import { tl } from '@mtcute/tl' import { TelegramClient } from '../client' -import { MtArgumentError, PeersIndex } from '../types' +import { PeersIndex } from '../types' import { _parseUpdate } from '../types/updates/parse-update' import { extractChannelIdFromUpdate } from '../utils/misc-utils' import { normalizeToInputChannel } from '../utils/peer-utils' diff --git a/packages/client/src/methods/users/get-me.ts b/packages/client/src/methods/users/get-me.ts index 2167f205..258d8e6a 100644 --- a/packages/client/src/methods/users/get-me.ts +++ b/packages/client/src/methods/users/get-me.ts @@ -1,6 +1,7 @@ +import { assertTypeIs } from '@mtcute/core/utils' + import { TelegramClient } from '../../client' import { User } from '../../types' -import { assertTypeIs } from '../../utils/type-assertion' /** * Get currently authorized user's full information diff --git a/packages/client/src/methods/users/resolve-peer.ts b/packages/client/src/methods/users/resolve-peer.ts index c1d340f3..66792929 100644 --- a/packages/client/src/methods/users/resolve-peer.ts +++ b/packages/client/src/methods/users/resolve-peer.ts @@ -3,18 +3,15 @@ import Long from 'long' import { getBasicPeerType, getMarkedPeerId, + MtTypeAssertionError, toggleChannelIdMark, } from '@mtcute/core' +import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - InputPeerLike, - MtPeerNotFoundError, - MtTypeAssertionError, -} from '../../types' +import { InputPeerLike, MtPeerNotFoundError } from '../../types' import { normalizeToInputPeer } from '../../utils/peer-utils' -import { assertTypeIs } from '../../utils/type-assertion' /** * Get the `InputPeer` of a known peer id. diff --git a/packages/client/src/methods/users/set-profile-photo.ts b/packages/client/src/methods/users/set-profile-photo.ts index 61972098..c14e9ca8 100644 --- a/packages/client/src/methods/users/set-profile-photo.ts +++ b/packages/client/src/methods/users/set-profile-photo.ts @@ -1,8 +1,9 @@ +import { MtArgumentError } from '@mtcute/core' import { fileIdToInputPhoto, tdFileId } from '@mtcute/file-id' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { InputFileLike, MtArgumentError, Photo } from '../../types' +import { InputFileLike, Photo } from '../../types' /** * Set a new profile photo or video. diff --git a/packages/client/src/types/bots/callback-query.ts b/packages/client/src/types/bots/callback-query.ts index 3ef704f5..6f8cef47 100644 --- a/packages/client/src/types/bots/callback-query.ts +++ b/packages/client/src/types/bots/callback-query.ts @@ -1,9 +1,14 @@ -import { BasicPeerType, getBasicPeerType, getMarkedPeerId } from '@mtcute/core' +import { + BasicPeerType, + getBasicPeerType, + getMarkedPeerId, + MtArgumentError, +} from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { encodeInlineMessageId } from '../../utils/inline-utils' -import { MtArgumentError, MtMessageNotFoundError } from '../errors' +import { MtMessageNotFoundError } from '../errors' import { Message } from '../messages' import { PeersIndex, User } from '../peers' import { makeInspectable } from '../utils' diff --git a/packages/client/src/types/bots/input/input-inline-result.ts b/packages/client/src/types/bots/input/input-inline-result.ts index 2abc4119..b756ca38 100644 --- a/packages/client/src/types/bots/input/input-inline-result.ts +++ b/packages/client/src/types/bots/input/input-inline-result.ts @@ -1,9 +1,9 @@ +import { MtArgumentError } from '@mtcute/core' import { fileIdToInputDocument, fileIdToInputPhoto } from '@mtcute/file-id' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../../client' import { extractFileName } from '../../../utils/file-utils' -import { MtArgumentError } from '../../errors' import { BotInlineMessage, InputInlineMessage } from './input-inline-message' export interface BaseInputInlineResult { @@ -903,8 +903,8 @@ export namespace BotInline { } } else if ( obj.type === 'video' && - obj.isEmbed && - typeof obj.media === 'string' + obj.isEmbed && + typeof obj.media === 'string' ) { sendMessage = { _: 'inputBotInlineMessageText', @@ -956,8 +956,9 @@ export namespace BotInline { let mime: string if (obj.type === 'video') mime = 'video/mp4' - else if (obj.type === 'audio') { mime = obj.mime ?? 'audio/mpeg' } else if (obj.type === 'gif') mime = obj.mime ?? 'video/mp4' - else if (obj.type === 'voice') mime = 'audio/ogg' + else if (obj.type === 'audio') { + mime = obj.mime ?? 'audio/mpeg' + } else if (obj.type === 'gif') { mime = obj.mime ?? 'video/mp4' } else if (obj.type === 'voice') mime = 'audio/ogg' else if (obj.type === 'file') { if (!obj.mime) { throw new MtArgumentError( @@ -991,7 +992,10 @@ export namespace BotInline { h: obj.height, }) } - } else if (obj.type === 'audio' || obj.type === 'voice') { + } else if ( + obj.type === 'audio' || + obj.type === 'voice' + ) { attributes.push({ _: 'documentAttributeAudio', voice: obj.type === 'voice', diff --git a/packages/client/src/types/conversation.ts b/packages/client/src/types/conversation.ts index c730dd31..d4f0c411 100644 --- a/packages/client/src/types/conversation.ts +++ b/packages/client/src/types/conversation.ts @@ -1,5 +1,10 @@ /* eslint-disable dot-notation */ -import { getMarkedPeerId, MaybeAsync } from '@mtcute/core' +import { + getMarkedPeerId, + MaybeAsync, + MtArgumentError, + MtTimeoutError, +} from '@mtcute/core' import { AsyncLock, ControllablePromise, @@ -9,7 +14,6 @@ import { import { tl } from '@mtcute/tl' import { TelegramClient } from '../client' -import { MtArgumentError, MtTimeoutError } from './errors' import { InputMediaLike } from './media' import { Message } from './messages' import { FormattedString } from './parser' diff --git a/packages/client/src/types/errors.ts b/packages/client/src/types/errors.ts index 0c080c27..621ca383 100644 --- a/packages/client/src/types/errors.ts +++ b/packages/client/src/types/errors.ts @@ -1,25 +1,16 @@ -/** - * Base class for all `@mtcute/client` errors - */ +import { MtcuteError } from '@mtcute/core' + import { InputPeerLike } from './peers' -export class MtClientError extends Error {} - -/** - * Method invocation was invalid because some argument - * passed was invalid. - */ -export class MtArgumentError extends MtClientError {} - /** * Could not find a peer by the provided information */ -export class MtPeerNotFoundError extends MtClientError {} +export class MtPeerNotFoundError extends MtcuteError {} /** * Could not find a message by the provided information */ -export class MtMessageNotFoundError extends MtClientError { +export class MtMessageNotFoundError extends MtcuteError { constructor( readonly peerId: number, readonly messageId: number, @@ -33,46 +24,6 @@ export class MtMessageNotFoundError extends MtClientError { } } -/** - * Either you requested or the server returned something - * that is not (yet) supported. - * - * Stay tuned for future updates! - */ -export class MtUnsupportedError extends MtClientError {} - -/** - * Server returned something of an unexpected type. - * - * This is usually a problem on library side. - * Feel free to open an issue about this! - */ -export class MtTypeAssertionError extends MtClientError { - /** - * Context at which the error occurred. - * Usually a user-friendly string containing name - * of the high-level API method, name of the TL - * RPC method, and path of the entity, - * like this: `signIn (@ auth.signIn -> user)` - */ - context: string - - /** Expected TL type */ - expected: string - - /** Actual TL type */ - actual: string - - constructor(context: string, expected: string, actual: string) { - super( - `Type assertion error at ${context}: expected ${expected}, but got ${actual}`, - ) - this.context = context - this.expected = expected - this.actual = actual - } -} - /** * Some method that requires a particular type of peer * is called, but the resolved peer type is invalid. @@ -80,7 +31,7 @@ export class MtTypeAssertionError extends MtClientError { * For example, when trying to get common chats * while providing another chat as `userId` */ -export class MtInvalidPeerTypeError extends MtClientError { +export class MtInvalidPeerTypeError extends MtcuteError { constructor(peer: InputPeerLike, expected: string) { super( `Provided identifier ${JSON.stringify(peer)} is not a ${expected}`, @@ -92,14 +43,8 @@ export class MtInvalidPeerTypeError extends MtClientError { * Trying to access to some property on an object that does not * contain that information. */ -export class MtEmptyError extends MtClientError { +export class MtEmptyError extends MtcuteError { constructor() { super('Property is not available on an empty object') } } - -export class MtTimeoutError extends MtClientError { - constructor(readonly timeout?: number) { - super(`Request timed out${timeout ? ` after ${timeout}ms` : ''}`) - } -} diff --git a/packages/client/src/types/files/web-document.ts b/packages/client/src/types/files/web-document.ts index 304b9085..5b9f42d1 100644 --- a/packages/client/src/types/files/web-document.ts +++ b/packages/client/src/types/files/web-document.ts @@ -1,7 +1,7 @@ +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { MtArgumentError } from '../errors' import { makeInspectable } from '../utils' import { FileLocation } from './file-location' diff --git a/packages/client/src/types/media/invoice.ts b/packages/client/src/types/media/invoice.ts index 7f7ecf52..d8e58173 100644 --- a/packages/client/src/types/media/invoice.ts +++ b/packages/client/src/types/media/invoice.ts @@ -1,7 +1,7 @@ +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { MtArgumentError } from '../errors' import { WebDocument } from '../files/web-document' import { _messageMediaFromTl, MessageMedia } from '../messages' import { makeInspectable } from '../utils' @@ -146,7 +146,9 @@ export class Invoice { get extendedMediaState(): InvoiceExtendedMediaState { if (!this.raw.extendedMedia) return 'none' - if (this.raw.extendedMedia._ === 'messageExtendedMediaPreview') { return 'preview' } + if (this.raw.extendedMedia._ === 'messageExtendedMediaPreview') { + return 'preview' + } return 'full' } @@ -158,7 +160,9 @@ export class Invoice { * Otherwise, throws an error. */ get extendedMediaPreview(): InvoiceExtendedMediaPreview { - if (this.raw.extendedMedia?._ !== 'messageExtendedMediaPreview') { throw new MtArgumentError('No extended media preview available') } + if (this.raw.extendedMedia?._ !== 'messageExtendedMediaPreview') { + throw new MtArgumentError('No extended media preview available') + } return (this._extendedMediaPreview ??= new InvoiceExtendedMediaPreview( this.client, diff --git a/packages/client/src/types/media/photo.ts b/packages/client/src/types/media/photo.ts index 7559ec95..5d35200c 100644 --- a/packages/client/src/types/media/photo.ts +++ b/packages/client/src/types/media/photo.ts @@ -1,7 +1,7 @@ +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { MtArgumentError } from '../errors' import { FileLocation } from '../files' import { makeInspectable } from '../utils' import { Thumbnail } from './thumbnail' diff --git a/packages/client/src/types/media/sticker.ts b/packages/client/src/types/media/sticker.ts index a433248e..9292881a 100644 --- a/packages/client/src/types/media/sticker.ts +++ b/packages/client/src/types/media/sticker.ts @@ -1,8 +1,8 @@ +import { MtArgumentError } from '@mtcute/core' import { tdFileId } from '@mtcute/file-id' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { MtArgumentError } from '../errors' import { StickerSet } from '../misc' import { makeInspectable } from '../utils' import { RawDocument } from './document' diff --git a/packages/client/src/types/media/thumbnail.ts b/packages/client/src/types/media/thumbnail.ts index 5ab89d48..e40b788d 100644 --- a/packages/client/src/types/media/thumbnail.ts +++ b/packages/client/src/types/media/thumbnail.ts @@ -1,5 +1,7 @@ import Long from 'long' +import { MtArgumentError, MtTypeAssertionError } from '@mtcute/core' +import { assertTypeIs } from '@mtcute/core/utils' import { tdFileId as td, toFileId, toUniqueFileId } from '@mtcute/file-id' import { tl } from '@mtcute/tl' @@ -9,8 +11,6 @@ import { strippedPhotoToJpg, svgPathToFile, } from '../../utils/file-utils' -import { assertTypeIs } from '../../utils/type-assertion' -import { MtArgumentError, MtTypeAssertionError } from '../errors' import { FileLocation } from '../files' import { makeInspectable } from '../utils' @@ -182,8 +182,12 @@ export class Thumbnail extends FileLocation { * Thumbnail type */ get type(): string { - if (this.raw._ === 'videoSizeEmojiMarkup') { return Thumbnail.THUMB_EMOJI_MARKUP } - if (this.raw._ === 'videoSizeStickerMarkup') { return Thumbnail.THUMB_STICKER_MARKUP } + if (this.raw._ === 'videoSizeEmojiMarkup') { + return Thumbnail.THUMB_EMOJI_MARKUP + } + if (this.raw._ === 'videoSizeStickerMarkup') { + return Thumbnail.THUMB_STICKER_MARKUP + } return this.raw.type } diff --git a/packages/client/src/types/media/venue.ts b/packages/client/src/types/media/venue.ts index f0fec9c2..2aeb73b4 100644 --- a/packages/client/src/types/media/venue.ts +++ b/packages/client/src/types/media/venue.ts @@ -1,7 +1,7 @@ +import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { assertTypeIs } from '../../utils/type-assertion' import { makeInspectable } from '../utils' import { Location } from './location' diff --git a/packages/client/src/types/media/web-page.ts b/packages/client/src/types/media/web-page.ts index 784b9698..2e609348 100644 --- a/packages/client/src/types/media/web-page.ts +++ b/packages/client/src/types/media/web-page.ts @@ -1,7 +1,7 @@ +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { MtArgumentError } from '../errors' import { makeInspectable } from '../utils' import { RawDocument } from './document' import { parseDocument } from './document-utils' diff --git a/packages/client/src/types/messages/message-media.ts b/packages/client/src/types/messages/message-media.ts index 8254b525..0db8e46b 100644 --- a/packages/client/src/types/messages/message-media.ts +++ b/packages/client/src/types/messages/message-media.ts @@ -1,7 +1,7 @@ +import { MtTypeAssertionError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { MtTypeAssertionError } from '../errors' import { Audio, Contact, diff --git a/packages/client/src/types/messages/message.ts b/packages/client/src/types/messages/message.ts index 2955c156..8bd63933 100644 --- a/packages/client/src/types/messages/message.ts +++ b/packages/client/src/types/messages/message.ts @@ -1,9 +1,14 @@ -import { assertNever, getMarkedPeerId, toggleChannelIdMark } from '@mtcute/core' +import { + assertNever, + getMarkedPeerId, + MtArgumentError, + MtTypeAssertionError, + toggleChannelIdMark, +} from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { BotKeyboard, ReplyMarkup } from '../bots' -import { MtArgumentError, MtTypeAssertionError } from '../errors' import { InputMediaLike, Sticker, WebPage } from '../media' import { FormattedString } from '../parser' import { Chat, InputPeerLike, PeersIndex, User } from '../peers' diff --git a/packages/client/src/types/messages/reactions.ts b/packages/client/src/types/messages/reactions.ts index 9a5d10a1..9c26fc5e 100644 --- a/packages/client/src/types/messages/reactions.ts +++ b/packages/client/src/types/messages/reactions.ts @@ -1,8 +1,8 @@ import { getMarkedPeerId } from '@mtcute/core' +import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { assertTypeIs } from '../../utils/type-assertion' import { PeersIndex, User } from '../peers' import { makeInspectable } from '../utils' diff --git a/packages/client/src/types/misc/sticker-set.ts b/packages/client/src/types/misc/sticker-set.ts index 61bf176e..2da60173 100644 --- a/packages/client/src/types/misc/sticker-set.ts +++ b/packages/client/src/types/misc/sticker-set.ts @@ -1,8 +1,9 @@ +import { MtTypeAssertionError } from '@mtcute/core' import { LongMap } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { MtEmptyError, MtTypeAssertionError } from '../errors' +import { MtEmptyError } from '../errors' import { InputFileLike } from '../files' import { MaskPosition, diff --git a/packages/client/src/types/peers/chat-invite-link.ts b/packages/client/src/types/peers/chat-invite-link.ts index d15e1019..8b001b93 100644 --- a/packages/client/src/types/peers/chat-invite-link.ts +++ b/packages/client/src/types/peers/chat-invite-link.ts @@ -1,7 +1,7 @@ +import { MtTypeAssertionError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { MtTypeAssertionError } from '../errors' import { makeInspectable } from '../utils' import { PeersIndex } from './index' import { User } from './user' diff --git a/packages/client/src/types/peers/chat-member.ts b/packages/client/src/types/peers/chat-member.ts index 4d33d45e..fba0f371 100644 --- a/packages/client/src/types/peers/chat-member.ts +++ b/packages/client/src/types/peers/chat-member.ts @@ -1,7 +1,7 @@ +import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { assertTypeIs } from '../../utils/type-assertion' import { makeInspectable } from '../utils' import { ChatPermissions } from './chat-permissions' import { PeersIndex } from './index' diff --git a/packages/client/src/types/peers/chat-photo.ts b/packages/client/src/types/peers/chat-photo.ts index 1925190f..a5ef509c 100644 --- a/packages/client/src/types/peers/chat-photo.ts +++ b/packages/client/src/types/peers/chat-photo.ts @@ -1,12 +1,11 @@ import Long from 'long' -import { toggleChannelIdMark } from '@mtcute/core' +import { MtArgumentError, toggleChannelIdMark } from '@mtcute/core' import { tdFileId, toFileId, toUniqueFileId } from '@mtcute/file-id' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { strippedPhotoToJpg } from '../../utils/file-utils' -import { MtArgumentError } from '../errors' import { FileLocation } from '../files' import { makeInspectable } from '../utils' diff --git a/packages/client/src/types/peers/chat.ts b/packages/client/src/types/peers/chat.ts index b5d8086f..4f3d766d 100644 --- a/packages/client/src/types/peers/chat.ts +++ b/packages/client/src/types/peers/chat.ts @@ -1,8 +1,12 @@ -import { getMarkedPeerId, MaybeArray } from '@mtcute/core' +import { + getMarkedPeerId, + MaybeArray, + MtArgumentError, + MtTypeAssertionError, +} from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { MtArgumentError, MtTypeAssertionError } from '../errors' import { InputMediaLike } from '../media' import { FormattedString } from '../parser' import { makeInspectable } from '../utils' diff --git a/packages/client/src/types/peers/peers-index.ts b/packages/client/src/types/peers/peers-index.ts index 1a2c445e..84b78996 100644 --- a/packages/client/src/types/peers/peers-index.ts +++ b/packages/client/src/types/peers/peers-index.ts @@ -1,7 +1,6 @@ +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' -import { MtArgumentError } from '../errors' - const ERROR_MSG = 'Given peer is not available in this index. This is most likely an internal library error.' diff --git a/packages/client/src/types/peers/user.ts b/packages/client/src/types/peers/user.ts index 8641cb58..3df1c852 100644 --- a/packages/client/src/types/peers/user.ts +++ b/packages/client/src/types/peers/user.ts @@ -1,8 +1,8 @@ +import { MtArgumentError } from '@mtcute/core' +import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { assertTypeIs } from '../../utils/type-assertion' -import { MtArgumentError } from '../errors' import { InputMediaLike } from '../media' import { FormattedString } from '../parser' import { makeInspectable } from '../utils' diff --git a/packages/client/src/types/updates/chosen-inline-result.ts b/packages/client/src/types/updates/chosen-inline-result.ts index b02919dd..c3f9437f 100644 --- a/packages/client/src/types/updates/chosen-inline-result.ts +++ b/packages/client/src/types/updates/chosen-inline-result.ts @@ -1,8 +1,9 @@ +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { encodeInlineMessageId } from '../../utils/inline-utils' -import { Location, MtArgumentError, PeersIndex, User } from '../' +import { Location, PeersIndex, User } from '../' import { makeInspectable } from '../utils' /** diff --git a/packages/client/src/types/updates/poll-vote.ts b/packages/client/src/types/updates/poll-vote.ts index 68e7a895..5f123fa7 100644 --- a/packages/client/src/types/updates/poll-vote.ts +++ b/packages/client/src/types/updates/poll-vote.ts @@ -1,8 +1,9 @@ +import { MtUnsupportedError } from '@mtcute/core' +import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { assertTypeIs } from '../../utils/type-assertion' -import { Chat, MtUnsupportedError, PeersIndex, User } from '../' +import { Chat, PeersIndex, User } from '../' import { makeInspectable } from '../utils' /** diff --git a/packages/client/src/types/updates/user-typing-update.ts b/packages/client/src/types/updates/user-typing-update.ts index 01181d15..3ddae2d5 100644 --- a/packages/client/src/types/updates/user-typing-update.ts +++ b/packages/client/src/types/updates/user-typing-update.ts @@ -1,14 +1,12 @@ -import { getBarePeerId, toggleChannelIdMark } from '@mtcute/core' +import { + getBarePeerId, + MtUnsupportedError, + toggleChannelIdMark, +} from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - BasicPeerType, - Chat, - MtUnsupportedError, - TypingStatus, - User, -} from '../' +import { BasicPeerType, Chat, TypingStatus, User } from '../' import { makeInspectable } from '../utils' /** diff --git a/packages/client/src/utils/file-utils.ts b/packages/client/src/utils/file-utils.ts index f5a8d809..a5d24481 100644 --- a/packages/client/src/utils/file-utils.ts +++ b/packages/client/src/utils/file-utils.ts @@ -1,4 +1,4 @@ -import { MtArgumentError } from '../types' +import { MtArgumentError } from '@mtcute/core' /** * Given file size, determine the appropriate chunk size (in KB) diff --git a/packages/client/src/utils/misc-utils.ts b/packages/client/src/utils/misc-utils.ts index 1821c007..dd9b451b 100644 --- a/packages/client/src/utils/misc-utils.ts +++ b/packages/client/src/utils/misc-utils.ts @@ -1,6 +1,7 @@ +import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' -import { MaybeDynamic, Message, MtClientError } from '../types' +import { MaybeDynamic, Message } from '../types' /** * Normalize phone number by stripping formatting @@ -8,7 +9,7 @@ import { MaybeDynamic, Message, MtClientError } from '../types' */ export function normalizePhoneNumber(phone: string): string { phone = phone.trim().replace(/[+()\s-]/g, '') - if (!phone.match(/^\d+$/)) throw new MtClientError('Invalid phone number') + if (!phone.match(/^\d+$/)) throw new MtArgumentError('Invalid phone number') return phone } @@ -25,7 +26,13 @@ export function extractChannelIdFromUpdate( if ('channelId' in upd) { res = upd.channelId - } else if ('message' in upd && typeof upd.message !== 'string' && 'peerId' in upd.message && upd.message.peerId && 'channelId' in upd.message.peerId) { + } else if ( + 'message' in upd && + typeof upd.message !== 'string' && + 'peerId' in upd.message && + upd.message.peerId && + 'channelId' in upd.message.peerId + ) { res = upd.message.peerId.channelId } diff --git a/packages/client/src/utils/type-assertion.ts b/packages/client/src/utils/type-assertion.ts deleted file mode 100644 index 77d71de6..00000000 --- a/packages/client/src/utils/type-assertion.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { tl } from '@mtcute/tl' - -import { MtTypeAssertionError } from '../types' - -export function assertTypeIs( - context: string, - obj: T, - expected: K, -): asserts obj is tl.FindByName { - if (obj._ !== expected) { - throw new MtTypeAssertionError(context, expected, obj._) - } -} diff --git a/packages/client/src/utils/updates-utils.ts b/packages/client/src/utils/updates-utils.ts index 1f7f4b53..7ed97b62 100644 --- a/packages/client/src/utils/updates-utils.ts +++ b/packages/client/src/utils/updates-utils.ts @@ -1,7 +1,6 @@ +import { MtTypeAssertionError } from '@mtcute/core' import { tl } from '@mtcute/tl' -import { MtTypeAssertionError } from '../types' - // dummy updates which are used for methods that return messages.affectedHistory. // that is not an update, but it carries info about pts, and we need to handle it diff --git a/packages/core/src/network/auth-key.ts b/packages/core/src/network/auth-key.ts index d2e5f690..a8e4b297 100644 --- a/packages/core/src/network/auth-key.ts +++ b/packages/core/src/network/auth-key.ts @@ -3,6 +3,7 @@ import Long from 'long' import { tl } from '@mtcute/tl' import { TlBinaryReader, TlReaderMap } from '@mtcute/tl-runtime' +import { MtcuteError } from '../types' import { buffersEqual, ICryptoProvider, Logger, randomBytes } from '../utils' import { createAesIgeForMessage } from '../utils/crypto/mtproto' @@ -41,7 +42,7 @@ export class AuthKey { serverSalt: Long, sessionId: Long, ): Promise { - if (!this.ready) throw new Error('Keys are not set up!') + if (!this.ready) throw new MtcuteError('Keys are not set up!') let padding = (16 /* header size */ + message.length + 12) /* min padding */ % 16 diff --git a/packages/core/src/network/authorization.ts b/packages/core/src/network/authorization.ts index 5603b3a5..43ddfcc0 100644 --- a/packages/core/src/network/authorization.ts +++ b/packages/core/src/network/authorization.ts @@ -9,6 +9,11 @@ import { TlSerializationCounter, } from '@mtcute/tl-runtime' +import { + MtArgumentError, + MtSecurityError, + MtTypeAssertionError, +} from '../types' import { bigIntToBuffer, bufferToBigInt, @@ -24,6 +29,7 @@ import { import { findKeyByFingerprints } from '../utils/crypto/keys' import { millerRabin } from '../utils/crypto/miller-rabin' import { generateKeyAndIvFromNonce } from '../utils/crypto/mtproto' +import { mtpAssertTypeIs } from '../utils/type-assertions' import { SessionConnection } from './session-connection' // Heavily based on code from https://github.com/LonamiWebs/Telethon/blob/master/telethon/network/authenticator.py @@ -57,14 +63,16 @@ function checkDhPrime(log: Logger, dhPrime: bigInt.BigInteger, g: number) { dhPrime.lesserOrEquals(TWO_POW_2047) || dhPrime.greaterOrEquals(TWO_POW_2048) ) { - throw new Error('Step 3: dh_prime is not in the 2048-bit range') + throw new MtSecurityError( + 'Step 3: dh_prime is not in the 2048-bit range', + ) } if (!millerRabin(dhPrime)) { - throw new Error('Step 3: dh_prime is not prime') + throw new MtSecurityError('Step 3: dh_prime is not prime') } if (!millerRabin(dhPrime.minus(1).divide(2))) { - throw new Error( + throw new MtSecurityError( 'Step 3: dh_prime is not a safe prime - (dh_prime-1)/2 is not prime', ) } @@ -91,12 +99,16 @@ function checkDhPrime(log: Logger, dhPrime: bigInt.BigInteger, g: number) { switch (g) { case 2: if (dhPrime.mod(8).notEquals(7)) { - throw new Error('Step 3: ivalid g - dh_prime mod 8 != 7') + throw new MtSecurityError( + 'Step 3: ivalid g - dh_prime mod 8 != 7', + ) } break case 3: if (dhPrime.mod(3).notEquals(2)) { - throw new Error('Step 3: ivalid g - dh_prime mod 3 != 2') + throw new MtSecurityError( + 'Step 3: ivalid g - dh_prime mod 3 != 2', + ) } break case 4: @@ -105,7 +117,7 @@ function checkDhPrime(log: Logger, dhPrime: bigInt.BigInteger, g: number) { const mod = dhPrime.mod(5) if (mod.notEquals(1) && mod.notEquals(4)) { - throw new Error( + throw new MtSecurityError( 'Step 3: ivalid g - dh_prime mod 5 != 1 && dh_prime mod 5 != 4', ) } @@ -115,7 +127,7 @@ function checkDhPrime(log: Logger, dhPrime: bigInt.BigInteger, g: number) { const mod = dhPrime.mod(24) if (mod.notEquals(19) && mod.notEquals(23)) { - throw new Error( + throw new MtSecurityError( 'Step 3: ivalid g - dh_prime mod 24 != 19 && dh_prime mod 24 != 23', ) } @@ -125,14 +137,14 @@ function checkDhPrime(log: Logger, dhPrime: bigInt.BigInteger, g: number) { const mod = dhPrime.mod(7) if (mod.notEquals(3) && mod.notEquals(5) && mod.notEquals(6)) { - throw new Error( + throw new MtSecurityError( 'Step 3: ivalid g - dh_prime mod 7 != 3 && dh_prime mod 7 != 5 && dh_prime mod 7 != 6', ) } break } default: - throw new Error(`Step 3: ivalid g - unknown g = ${g}`) + throw new MtSecurityError(`Step 3: ivalid g - unknown g = ${g}`) } checkedPrime.generators.push(g) @@ -151,7 +163,7 @@ async function rsaPad( const keyExponent = bigInt(key.exponent, 16) if (data.length > 144) { - throw new Error('Failed to pad: too big data') + throw new MtArgumentError('Failed to pad: too big data') } data = Buffer.concat([data, randomBytes(192 - data.length)]) @@ -265,10 +277,10 @@ export async function doAuthorization( await sendPlainMessage({ _: 'mt_req_pq_multi', nonce }) const resPq = await readNext() - if (resPq._ !== 'mt_resPQ') throw new Error('Step 1: answer was ' + resPq._) + mtpAssertTypeIs('auth step 1', resPq, 'mt_resPQ') if (!buffersEqual(resPq.nonce, nonce)) { - throw new Error('Step 1: invalid nonce from server') + throw new MtSecurityError('Step 1: invalid nonce from server') } const serverKeys = resPq.serverPublicKeyFingerprints.map((it) => @@ -280,7 +292,7 @@ export async function doAuthorization( const publicKey = findKeyByFingerprints(serverKeys) if (!publicKey) { - throw new Error( + throw new MtSecurityError( 'Step 2: Could not find server public key with any of these fingerprints: ' + serverKeys.join(', '), ) @@ -330,19 +342,13 @@ export async function doAuthorization( }) const serverDhParams = await readNext() - if (!mtp.isAnyServer_DH_Params(serverDhParams)) { - throw new Error('Step 2.1: answer was ' + serverDhParams._) - } - - if (serverDhParams._ !== 'mt_server_DH_params_ok') { - throw new Error('Step 2.1: answer was ' + serverDhParams._) - } + mtpAssertTypeIs('auth step 2', serverDhParams, 'mt_server_DH_params_ok') if (!buffersEqual(serverDhParams.nonce, nonce)) { - throw Error('Step 2: invalid nonce from server') + throw new MtSecurityError('Step 2: invalid nonce from server') } if (!buffersEqual(serverDhParams.serverNonce, resPq.serverNonce)) { - throw Error('Step 2: invalid server nonce from server') + throw new MtSecurityError('Step 2: invalid server nonce from server') } // type was removed from schema in July 2021 @@ -350,14 +356,14 @@ export async function doAuthorization( // // why would i want to do that? we are gonna fail anyways. // // let expectedNnh = (await crypto.sha1(newNonce)).slice(4, 20) // // if (!buffersEqual(serverDhParams.newNonceHash, expectedNnh)) - // // throw new Error('Step 2: invalid DH fail nonce from server') - // throw new Error('Step 2: server DH failed') + // // throw new MtSecurityError('Step 2: invalid DH fail nonce from server') + // throw new MtSecurityError('Step 2: server DH failed') // } log.debug('server DH ok') if (serverDhParams.encryptedAnswer.length % 16 !== 0) { - throw new Error('Step 2: AES block size is invalid') + throw new MtSecurityError('Step 2: AES block size is invalid') } // Step 3: complete DH exchange @@ -385,12 +391,11 @@ export async function doAuthorization( ), ) ) { - throw new Error('Step 3: invalid inner data hash') + throw new MtSecurityError('Step 3: invalid inner data hash') } - if (serverDhInner._ !== 'mt_server_DH_inner_data') { - throw Error('Step 3: inner data was ' + serverDhInner._) - } + mtpAssertTypeIs('auth step 3', serverDhInner, 'mt_server_DH_inner_data') + if (!buffersEqual(serverDhInner.nonce, nonce)) { throw Error('Step 3: invalid nonce from server') } @@ -424,28 +429,28 @@ export async function doAuthorization( g.lesserOrEquals(1) || g.greaterOrEquals(dhPrime.minus(bigInt.one)) ) { - throw new Error('g is not within (1, dh_prime - 1)') + throw new MtSecurityError('g is not within (1, dh_prime - 1)') } if ( gA.lesserOrEquals(1) || gA.greaterOrEquals(dhPrime.minus(bigInt.one)) ) { - throw new Error('g_a is not within (1, dh_prime - 1)') + throw new MtSecurityError('g_a is not within (1, dh_prime - 1)') } if ( gB.lesserOrEquals(1) || gB.greaterOrEquals(dhPrime.minus(bigInt.one)) ) { - throw new Error('g_b is not within (1, dh_prime - 1)') + throw new MtSecurityError('g_b is not within (1, dh_prime - 1)') } if (gA.lt(DH_SAFETY_RANGE) || gA.gt(dhPrime.minus(DH_SAFETY_RANGE))) { - throw new Error( + throw new MtSecurityError( 'g_a is not within (2^{2048-64}, dh_prime - 2^{2048-64})', ) } if (gB.lt(DH_SAFETY_RANGE) || gB.gt(dhPrime.minus(DH_SAFETY_RANGE))) { - throw new Error( + throw new MtSecurityError( 'g_b is not within (2^{2048-64}, dh_prime - 2^{2048-64})', ) } @@ -488,7 +493,11 @@ export async function doAuthorization( const dhGen = await readNext() if (!mtp.isAnySet_client_DH_params_answer(dhGen)) { - throw new Error('Step 4: answer was ' + dhGen._) + throw new MtTypeAssertionError( + 'auth step 4', + 'set_client_DH_params_answer', + dhGen._, + ) } if (!buffersEqual(dhGen.nonce, nonce)) { @@ -502,7 +511,11 @@ export async function doAuthorization( if (dhGen._ === 'mt_dh_gen_fail') { // in theory i would be supposed to calculate newNonceHash, but why, we are failing anyway - throw new Error('Step 4: server DH returned failure') + throw new MtTypeAssertionError( + 'auth step 4', + '!mt_dh_gen_fail', + dhGen._, + ) } if (dhGen._ === 'mt_dh_gen_retry') { diff --git a/packages/core/src/network/mtproto-session.ts b/packages/core/src/network/mtproto-session.ts index b8e46c4a..4d575062 100644 --- a/packages/core/src/network/mtproto-session.ts +++ b/packages/core/src/network/mtproto-session.ts @@ -8,6 +8,7 @@ import { TlWriterMap, } from '@mtcute/tl-runtime' +import { MtcuteError } from '../types' import { ControllablePromise, Deque, @@ -183,7 +184,7 @@ export class MtprotoSession { if (!keepPending) { for (const info of this.pendingMessages.values()) { if (info._ === 'rpc') { - info.rpc.promise.reject(new Error('Session is reset')) + info.rpc.promise.reject(new MtcuteError('Session is reset')) } } this.pendingMessages.clear() @@ -197,7 +198,7 @@ export class MtprotoSession { const rpc = this.queuedRpc.popFront()! if (rpc.sent === false) { - rpc.promise.reject(new Error('Session is reset')) + rpc.promise.reject(new MtcuteError('Session is reset')) } } } @@ -264,7 +265,7 @@ export class MtprotoSession { data: Buffer, callback: Parameters[2], ): Promise { - if (!this._authKey.ready) throw new Error('Keys are not set up!') + if (!this._authKey.ready) throw new MtcuteError('Keys are not set up!') const authKeyId = data.slice(0, 8) diff --git a/packages/core/src/network/network-manager.ts b/packages/core/src/network/network-manager.ts index bf5e3ee1..56965f35 100644 --- a/packages/core/src/network/network-manager.ts +++ b/packages/core/src/network/network-manager.ts @@ -2,12 +2,14 @@ import { tl } from '@mtcute/tl' import { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime' import { ITelegramStorage } from '../storage' +import { MtArgumentError, MtcuteError } from '../types' import { createControllablePromise, ICryptoProvider, Logger, sleep, } from '../utils' +import { assertTypeIs } from '../utils/type-assertions' import { ConfigManager } from './config-manager' import { MultiSessionConnection } from './multi-session-connection' import { PersistentConnectionParams } from './persistent-connection' @@ -500,7 +502,7 @@ export class NetworkManager { }) if (!main || !media) { - throw new Error(`Could not find DC ${dcId}`) + throw new MtArgumentError(`Could not find DC ${dcId}`) } return { main, media } @@ -586,12 +588,12 @@ export class NetworkManager { */ async connect(defaultDcs: ITelegramStorage.DcOptions): Promise { if (defaultDcs.main.id !== defaultDcs.media.id) { - throw new Error('Default DCs must be the same') + throw new MtArgumentError('Default DCs must be the same') } if (this._dcConnections.has(defaultDcs.main.id)) { // shouldn't happen - throw new Error('DC manager already exists') + throw new MtArgumentError('DC manager already exists') } const dc = new DcConnectionManager(this, defaultDcs.main.id, defaultDcs) @@ -626,11 +628,7 @@ export class NetworkManager { { manager }, ) - if (res._ !== 'auth.authorization') { - throw new Error( - `Unexpected response from auth.importAuthorization: ${res._}`, - ) - } + assertTypeIs('auth.importAuthorization', res, 'auth.authorization') promise.resolve() delete this._pendingExports[manager.dcId] @@ -713,7 +711,7 @@ export class NetworkManager { stack?: string, ): Promise { if (!this._primaryDc) { - throw new Error('Not connected to any DC') + throw new MtcuteError('Not connected to any DC') } const floodSleepThreshold = @@ -860,7 +858,7 @@ export class NetworkManager { if (!dc) { if (!this._primaryDc) { - throw new Error('Not connected to any DC') + throw new MtcuteError('Not connected to any DC') } // guess based on the provided delegate. it is most likely correct, @@ -876,7 +874,7 @@ export class NetworkManager { } getPrimaryDcId() { - if (!this._primaryDc) throw new Error('Not connected to any DC') + if (!this._primaryDc) throw new MtcuteError('Not connected to any DC') return this._primaryDc.dcId } diff --git a/packages/core/src/network/persistent-connection.ts b/packages/core/src/network/persistent-connection.ts index 12d5a170..23c57882 100644 --- a/packages/core/src/network/persistent-connection.ts +++ b/packages/core/src/network/persistent-connection.ts @@ -2,6 +2,7 @@ import EventEmitter from 'events' import { tl } from '@mtcute/tl' +import { MtcuteError } from '../types' import { ICryptoProvider, Logger } from '../utils' import { ReconnectionStrategy } from './reconnection' import { @@ -166,9 +167,9 @@ export abstract class PersistentConnection extends EventEmitter { connect(): void { if (this.isConnected) { - throw new Error('Connection is already opened!') + throw new MtcuteError('Connection is already opened!') } - if (this._destroyed) throw new Error('Connection is already destroyed!') + if (this._destroyed) { throw new MtcuteError('Connection is already destroyed!') } if (this._reconnectionTimeout != null) { clearTimeout(this._reconnectionTimeout) diff --git a/packages/core/src/network/session-connection.ts b/packages/core/src/network/session-connection.ts index 8cfa4a0c..8cd1796b 100644 --- a/packages/core/src/network/session-connection.ts +++ b/packages/core/src/network/session-connection.ts @@ -12,6 +12,7 @@ import { } from '@mtcute/tl-runtime' import { gzipDeflate, gzipInflate } from '@mtcute/tl-runtime/src/platform/gzip' +import { MtArgumentError, MtcuteError, MtTimeoutError } from '../types' import { ControllablePromise, createCancellablePromise, @@ -123,7 +124,7 @@ export class SessionConnection extends PersistentConnection { Object.values(this._pendingWaitForUnencrypted).forEach( ([prom, timeout]) => { - prom.reject(new Error('Connection closed')) + prom.reject(new MtcuteError('Connection closed')) clearTimeout(timeout) }, ) @@ -456,7 +457,7 @@ export class SessionConnection extends PersistentConnection { res.errorCode, res.errorMessage, ) - throw new Error('Failed to bind temporary key') + throw new MtcuteError('Failed to bind temporary key') } // now we can swap the keys (secondary becomes primary, @@ -506,7 +507,7 @@ export class SessionConnection extends PersistentConnection { waitForUnencryptedMessage(timeout = 5000): Promise { const promise = createControllablePromise() const timeoutId = setTimeout(() => { - promise.reject(new Error('Timeout')) + promise.reject(new MtTimeoutError(timeout)) this._pendingWaitForUnencrypted = this._pendingWaitForUnencrypted.filter( (it) => it[0] !== promise, @@ -1453,7 +1454,9 @@ export class SessionConnection extends PersistentConnection { // and since we resend them, it will get resent after reconnection and // that will be an endless loop of reconnections. we don't want that, // and payloads this large are usually a sign of an error in the code. - throw new Error(`Payload is too big (${content.length} > 1044404)`) + throw new MtArgumentError( + `Payload is too big (${content.length} > 1044404)`, + ) } // gzip @@ -1533,7 +1536,7 @@ export class SessionConnection extends PersistentConnection { private _cancelRpc(rpc: PendingRpc, onTimeout = false): void { if (rpc.cancelled && !onTimeout) { - throw new Error('RPC was already cancelled') + throw new MtcuteError('RPC was already cancelled') } if (!onTimeout && rpc.timeout) { diff --git a/packages/core/src/network/transports/tcp.ts b/packages/core/src/network/transports/tcp.ts index fa647a5e..df8a7c09 100644 --- a/packages/core/src/network/transports/tcp.ts +++ b/packages/core/src/network/transports/tcp.ts @@ -3,6 +3,7 @@ import { connect, Socket } from 'net' import { tl } from '@mtcute/tl' +import { MtcuteError } from '../../types' import { ICryptoProvider, Logger } from '../../utils' import { IPacketCodec, ITelegramTransport, TransportState } from './abstract' import { IntermediatePacketCodec } from './intermediate' @@ -49,7 +50,7 @@ export abstract class BaseTcpTransport // eslint-disable-next-line @typescript-eslint/no-unused-vars connect(dc: tl.RawDcOption, testMode: boolean): void { if (this._state !== TransportState.Idle) { - throw new Error('Transport is not IDLE') + throw new MtcuteError('Transport is not IDLE') } if (!this.packetCodecInitialized) { @@ -125,7 +126,7 @@ export abstract class BaseTcpTransport async send(bytes: Buffer): Promise { if (this._state !== TransportState.Ready) { - throw new Error('Transport is not READY') + throw new MtcuteError('Transport is not READY') } const framed = await this._packetCodec.encode(bytes) diff --git a/packages/core/src/network/transports/websocket.ts b/packages/core/src/network/transports/websocket.ts index 5da1e0e8..98a6592c 100644 --- a/packages/core/src/network/transports/websocket.ts +++ b/packages/core/src/network/transports/websocket.ts @@ -2,6 +2,7 @@ import EventEmitter from 'events' import { tl } from '@mtcute/tl' +import { MtcuteError, MtUnsupportedError } from '../../types' import { ICryptoProvider, Logger, typedArrayToBuffer } from '../../utils' import { IPacketCodec, ITelegramTransport, TransportState } from './abstract' import { IntermediatePacketCodec } from './intermediate' @@ -57,7 +58,7 @@ export abstract class BaseWebSocketTransport super() if (!ws) { - throw new Error( + throw new MtUnsupportedError( 'To use WebSocket transport with NodeJS, install `ws` package.', ) } @@ -93,7 +94,7 @@ export abstract class BaseWebSocketTransport connect(dc: tl.RawDcOption, testMode: boolean): void { if (this._state !== TransportState.Idle) { - throw new Error('Transport is not IDLE') + throw new MtcuteError('Transport is not IDLE') } if (!this.packetCodecInitialized) { @@ -164,7 +165,7 @@ export abstract class BaseWebSocketTransport async send(bytes: Buffer): Promise { if (this._state !== TransportState.Ready) { - throw new Error('Transport is not READY') + throw new MtcuteError('Transport is not READY') } const framed = await this._packetCodec.encode(bytes) diff --git a/packages/core/src/storage/json-file.ts b/packages/core/src/storage/json-file.ts index eaae2ebd..9acd4813 100644 --- a/packages/core/src/storage/json-file.ts +++ b/packages/core/src/storage/json-file.ts @@ -1,6 +1,7 @@ import type * as exitHookNs from 'exit-hook' import type * as fsNs from 'fs' +import { MtUnsupportedError } from '../types' import { JsonMemoryStorage } from './json' type fs = typeof fsNs @@ -52,7 +53,7 @@ export class JsonFileStorage extends JsonMemoryStorage { super() if (!fs || !fs.readFile) { - throw new Error('Node fs module is not available!') + throw new MtUnsupportedError('Node fs module is not available!') } this._filename = filename @@ -60,7 +61,7 @@ export class JsonFileStorage extends JsonMemoryStorage { this._cleanup = params?.cleanup ?? Boolean(exitHook) if (this._cleanup && !exitHook) { - throw new Error( + throw new MtUnsupportedError( 'Cleanup on exit is supported through `exit-hook` library, install it first!', ) } diff --git a/packages/core/src/storage/localstorage.ts b/packages/core/src/storage/localstorage.ts index a7835b57..9c102bcd 100644 --- a/packages/core/src/storage/localstorage.ts +++ b/packages/core/src/storage/localstorage.ts @@ -1,3 +1,4 @@ +import { MtUnsupportedError } from '../types' import { JsonMemoryStorage } from './json' export class LocalstorageStorage extends JsonMemoryStorage { @@ -7,7 +8,7 @@ export class LocalstorageStorage extends JsonMemoryStorage { super() if (typeof localStorage === 'undefined') { - throw new Error('localStorage is not available!') + throw new MtUnsupportedError('localStorage is not available!') } this._key = key diff --git a/packages/core/src/storage/memory.ts b/packages/core/src/storage/memory.ts index 9691cf5b..4419388b 100644 --- a/packages/core/src/storage/memory.ts +++ b/packages/core/src/storage/memory.ts @@ -151,7 +151,9 @@ export class MemoryStorage implements ITelegramStorage, IStateStorage { (ent: ITelegramStorage.PeerInfo) => { if (ent.phone) obj.phoneIndex.set(ent.phone, ent.id) - if (ent.username) { obj.usernameIndex.set(ent.username, ent.id) } + if (ent.username) { + obj.usernameIndex.set(ent.username, ent.id) + } }, ) } @@ -291,8 +293,6 @@ export class MemoryStorage implements ITelegramStorage, IStateStorage { accessHash: peerInfo.accessHash, } } - - throw new Error(`Invalid peer type: ${peerInfo.type}`) } getPeerById(peerId: number): tl.TypeInputPeer | null { diff --git a/packages/core/src/types/errors.ts b/packages/core/src/types/errors.ts new file mode 100644 index 00000000..04f26a50 --- /dev/null +++ b/packages/core/src/types/errors.ts @@ -0,0 +1,65 @@ +/** + * Base class for all mtcute errors + */ +export class MtcuteError extends Error {} + +/** + * Method invocation was invalid because some argument + * passed was invalid. + */ +export class MtArgumentError extends MtcuteError {} + +/** + * Something isn't right with security of the connection. + */ +export class MtSecurityError extends MtcuteError {} + +/** + * Either you requested or the server returned something + * that is not (yet) supported. + * + * Stay tuned for future updates! + * + * In some cases, this error may mean that you are missing some + * optional peer dependencies, or that the feature is not supported + * in the current environment. + */ +export class MtUnsupportedError extends MtcuteError {} + +/** + * Server returned something of an unexpected type. + * + * This is usually a problem on library side. + * Feel free to open an issue about this! + */ +export class MtTypeAssertionError extends MtcuteError { + /** + * Context at which the error occurred. + * Usually a user-friendly string containing name + * of the high-level API method, name of the TL + * RPC method, and path of the entity, + * like this: `signIn (@ auth.signIn -> user)` + */ + context: string + + /** Expected TL type */ + expected: string + + /** Actual TL type */ + actual: string + + constructor(context: string, expected: string, actual: string) { + super( + `Type assertion error at ${context}: expected ${expected}, but got ${actual}`, + ) + this.context = context + this.expected = expected + this.actual = actual + } +} + +export class MtTimeoutError extends MtcuteError { + constructor(readonly timeout?: number) { + super(`Request timed out${timeout ? ` after ${timeout}ms` : ''}`) + } +} diff --git a/packages/core/src/types/index.ts b/packages/core/src/types/index.ts index 9a16b6b7..c7b15238 100644 --- a/packages/core/src/types/index.ts +++ b/packages/core/src/types/index.ts @@ -1,2 +1,3 @@ +export * from './errors' export * from './peers' export * from './utils' diff --git a/packages/core/src/utils/crypto/password.ts b/packages/core/src/utils/crypto/password.ts index 76ab664a..2a7c08bc 100644 --- a/packages/core/src/utils/crypto/password.ts +++ b/packages/core/src/utils/crypto/password.ts @@ -2,6 +2,7 @@ import bigInt from 'big-integer' import { tl } from '@mtcute/tl' +import { MtSecurityError, MtUnsupportedError } from '../../types' import { bigIntToBuffer, bufferToBigInt } from '../bigint-utils' import { randomBytes, xorBuffer } from '../buffer-utils' import { ICryptoProvider } from './abstract' @@ -84,7 +85,7 @@ export async function computeSrpParams( request.currentAlgo._ !== 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow' ) { - throw new Error(`Unknown algo ${request.currentAlgo?._}`) + throw new MtUnsupportedError(`Unknown algo ${request.currentAlgo?._}`) } const algo = request.currentAlgo @@ -92,11 +93,11 @@ export async function computeSrpParams( // here and after: underscored variables are buffers, non-underscored are bigInts if (!request.srpB) { - throw new Error('SRP_B is not present in the request') + throw new MtSecurityError('SRP_B is not present in the request') } if (!request.srpId) { - throw new Error('SRP_ID is not present in the request') + throw new MtSecurityError('SRP_ID is not present in the request') } const g = bigInt(algo.g) diff --git a/packages/core/src/utils/peer-utils.ts b/packages/core/src/utils/peer-utils.ts index 80858fc6..0926ccb0 100644 --- a/packages/core/src/utils/peer-utils.ts +++ b/packages/core/src/utils/peer-utils.ts @@ -1,6 +1,6 @@ import { tl } from '@mtcute/tl' -import { BasicPeerType } from '../types' +import { BasicPeerType, MtArgumentError, MtUnsupportedError } from '../types' // src: https://github.com/tdlib/td/blob/master/td/telegram/DialogId.h const ZERO_CHANNEL_ID = -1000000000000 @@ -50,10 +50,21 @@ export function getBarePeerId(peer: tl.TypePeer): number { * - ID is negated and `-1e12` is subtracted for channels */ export function getMarkedPeerId(peerId: number, peerType: BasicPeerType): number -export function getMarkedPeerId(peer: tl.TypePeer | tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel): number +export function getMarkedPeerId( + peer: + | tl.TypePeer + | tl.TypeInputPeer + | tl.TypeInputUser + | tl.TypeInputChannel +): number export function getMarkedPeerId( - peer: tl.TypePeer | tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel | number, + peer: + | tl.TypePeer + | tl.TypeInputPeer + | tl.TypeInputUser + | tl.TypeInputChannel + | number, peerType?: BasicPeerType, ): number { if (typeof peer === 'number') { @@ -65,7 +76,7 @@ export function getMarkedPeerId( case 'channel': return ZERO_CHANNEL_ID - peer } - throw new Error('Invalid peer type') + throw new MtArgumentError('Invalid peer type') } switch (peer._) { @@ -82,7 +93,7 @@ export function getMarkedPeerId( return ZERO_CHANNEL_ID - peer.channelId } - throw new Error('Invalid peer') + throw new MtArgumentError('Invalid peer') } /** @@ -105,17 +116,19 @@ export function getBasicPeerType(peer: tl.TypePeer | number): BasicPeerType { return 'chat' } - if (MIN_MARKED_CHANNEL_ID <= peer && peer !== ZERO_CHANNEL_ID) { return 'channel' } + if (MIN_MARKED_CHANNEL_ID <= peer && peer !== ZERO_CHANNEL_ID) { + return 'channel' + } if (MAX_SECRET_CHAT_ID <= peer && peer !== ZERO_SECRET_CHAT_ID) { // return 'secret' - throw new Error('Unsupported') + throw new MtUnsupportedError('Secret chats are not supported') } } else if (peer > 0 && peer <= MAX_USER_ID) { return 'user' } - throw new Error(`Invalid marked peer id: ${peer}`) + throw new MtArgumentError(`Invalid marked peer id: ${peer}`) } /** @@ -134,8 +147,6 @@ export function markedPeerIdToBare(peerId: number): number { case 'channel': return toggleChannelIdMark(peerId) } - - throw new Error('Invalid marked peer id') } /** diff --git a/packages/core/src/utils/platform/transport.web.ts b/packages/core/src/utils/platform/transport.web.ts index cdd5808a..8a0bc536 100644 --- a/packages/core/src/utils/platform/transport.web.ts +++ b/packages/core/src/utils/platform/transport.web.ts @@ -1,11 +1,13 @@ import { WebSocketTransport } from '../../network' +import { MtUnsupportedError } from '../../types' /** @internal */ export const _defaultTransportFactory = - typeof WebSocket === 'undefined' ? // if no websocket, throw an error i guess ¯\_(ツ)_/¯ + // if no websocket, throw an error i guess ¯\_(ツ)_/¯ // (user can still implement something on their own) + typeof WebSocket === 'undefined' ? () => { - throw new Error( + throw new MtUnsupportedError( 'Neither TCP nor WebSocket are available. Please pass a Transport factory explicitly', ) } : diff --git a/packages/core/src/utils/string-session.ts b/packages/core/src/utils/string-session.ts index 8ca064d5..19badb0f 100644 --- a/packages/core/src/utils/string-session.ts +++ b/packages/core/src/utils/string-session.ts @@ -7,6 +7,7 @@ import { } from '@mtcute/tl-runtime' import { ITelegramStorage } from '../storage' +import { MtArgumentError } from '../types' import { encodeUrlSafeBase64, parseUrlSafeBase64 } from './buffer-utils' export interface StringSessionData { @@ -26,7 +27,9 @@ export function writeStringSession( const version = data.version if (version !== 1 && version !== 2) { - throw new Error(`Unsupported string session version: ${version}`) + throw new MtArgumentError( + `Unsupported string session version: ${version}`, + ) } let flags = 0 @@ -85,7 +88,9 @@ export function readStringSession( primaryDc if (primaryDc._ !== 'dcOption') { - throw new Error(`Invalid session string (dc._ = ${primaryDc._})`) + throw new MtArgumentError( + `Invalid session string (dc._ = ${primaryDc._})`, + ) } let self: ITelegramStorage.SelfInfo | null = null diff --git a/packages/core/src/utils/tl-json.ts b/packages/core/src/utils/tl-json.ts index 04fb516a..ecb4c5c7 100644 --- a/packages/core/src/utils/tl-json.ts +++ b/packages/core/src/utils/tl-json.ts @@ -1,5 +1,7 @@ import { tl } from '@mtcute/tl' +import { MtArgumentError } from '../types' + /** * Convert a JS object to TL JSON * @@ -12,9 +14,13 @@ export function jsonToTlJson(obj: unknown): tl.TypeJSONValue { if (typeof obj === 'number') return { _: 'jsonNumber', value: obj } if (typeof obj === 'string') return { _: 'jsonString', value: obj } - if (Array.isArray(obj)) { return { _: 'jsonArray', value: obj.map(jsonToTlJson) } } + if (Array.isArray(obj)) { + return { _: 'jsonArray', value: obj.map(jsonToTlJson) } + } - if (typeof obj !== 'object') { throw new Error(`Unsupported type: ${typeof obj}`) } + if (typeof obj !== 'object') { + throw new MtArgumentError(`Unsupported type: ${typeof obj}`) + } const items: tl.TypeJSONObjectValue[] = [] diff --git a/packages/core/src/utils/type-assertions.ts b/packages/core/src/utils/type-assertions.ts index 44488f59..60c66341 100644 --- a/packages/core/src/utils/type-assertions.ts +++ b/packages/core/src/utils/type-assertions.ts @@ -1,3 +1,7 @@ +import { mtp, tl } from '@mtcute/tl' + +import { MtTypeAssertionError } from '../types' + // mostly taken from https://github.com/robertmassaioli/ts-is-present export function isPresent(t: T | undefined | null | void): t is T { @@ -46,7 +50,29 @@ export function hasValueAtKey( k: K, v: V, ) { - return function (a: T & { [k in K]: unknown }): a is T & { [k in K]: V } { + return function ( + a: T & { [k in K]: unknown }, + ): a is T & { [k in K]: V } { return a[k] === v } } + +export function assertTypeIs( + context: string, + obj: T, + expected: K, +): asserts obj is tl.FindByName { + if (obj._ !== expected) { + throw new MtTypeAssertionError(context, expected, obj._) + } +} + +export function mtpAssertTypeIs( + context: string, + obj: T, + expected: K, +): asserts obj is mtp.FindByName { + if (obj._ !== expected) { + throw new MtTypeAssertionError(context, expected, obj._) + } +} diff --git a/packages/dispatcher/src/callback-data-builder.ts b/packages/dispatcher/src/callback-data-builder.ts index aeffbbfd..9aacd634 100644 --- a/packages/dispatcher/src/callback-data-builder.ts +++ b/packages/dispatcher/src/callback-data-builder.ts @@ -1,5 +1,5 @@ -import { CallbackQuery, MtArgumentError } from '@mtcute/client' -import { MaybeArray } from '@mtcute/core' +import { CallbackQuery } from '@mtcute/client' +import { MaybeArray, MtArgumentError } from '@mtcute/core' import { UpdateFilter } from './filters' diff --git a/packages/dispatcher/src/dispatcher.ts b/packages/dispatcher/src/dispatcher.ts index 7f6fcc54..f43fcb00 100644 --- a/packages/dispatcher/src/dispatcher.ts +++ b/packages/dispatcher/src/dispatcher.ts @@ -14,7 +14,6 @@ import { InlineQuery, MaybeAsync, Message, - MtArgumentError, ParsedUpdate, PeersIndex, PollUpdate, @@ -56,6 +55,7 @@ import { StateKeyDelegate, UpdateState, } from './state' +import { MtArgumentError } from '@mtcute/core' /** * Updates dispatcher diff --git a/packages/dispatcher/src/state/update-state.ts b/packages/dispatcher/src/state/update-state.ts index b41fe66f..b1b59a93 100644 --- a/packages/dispatcher/src/state/update-state.ts +++ b/packages/dispatcher/src/state/update-state.ts @@ -1,4 +1,4 @@ -import { MtArgumentError, MtClientError } from '@mtcute/client' +import { MtArgumentError, MtcuteError } from '@mtcute/core' import { sleep } from '@mtcute/core/utils' import { IStateStorage } from './storage' @@ -6,7 +6,7 @@ import { IStateStorage } from './storage' /** * Error thrown by `.rateLimit()` */ -export class RateLimitError extends MtClientError { +export class RateLimitError extends MtcuteError { constructor(readonly reset: number) { super('You are being rate limited.') } diff --git a/packages/http-proxy/index.ts b/packages/http-proxy/index.ts index 472bb306..b8914f86 100644 --- a/packages/http-proxy/index.ts +++ b/packages/http-proxy/index.ts @@ -6,6 +6,7 @@ import { connect as connectTls, SecureContextOptions } from 'tls' import { BaseTcpTransport, IntermediatePacketCodec, + MtcuteError, tl, TransportState, } from '@mtcute/core' @@ -80,7 +81,7 @@ export abstract class BaseHttpProxyTcpTransport extends BaseTcpTransport { connect(dc: tl.RawDcOption): void { if (this._state !== TransportState.Idle) { - throw new Error('Transport is not IDLE') + throw new MtcuteError('Transport is not IDLE') } if (!this.packetCodecInitialized) { diff --git a/packages/mtproxy/index.ts b/packages/mtproxy/index.ts index 75394bea..a57d78f6 100644 --- a/packages/mtproxy/index.ts +++ b/packages/mtproxy/index.ts @@ -6,6 +6,9 @@ import { BaseTcpTransport, IntermediatePacketCodec, IPacketCodec, + MtcuteError, + MtSecurityError, + MtUnsupportedError, ObfuscatedPacketCodec, PaddedIntermediatePacketCodec, tl, @@ -71,11 +74,11 @@ export class MtProxyTcpTransport extends BaseTcpTransport { } if (secret.length > 17 + MAX_DOMAIN_LENGTH) { - throw new Error('Invalid secret: too long') + throw new MtSecurityError('Invalid secret: too long') } if (secret.length < 16) { - throw new Error('Invalid secret: too short') + throw new MtSecurityError('Invalid secret: too short') } if (secret.length === 16) { @@ -87,7 +90,7 @@ export class MtProxyTcpTransport extends BaseTcpTransport { this._rawSecret = secret.slice(1, 17) this._fakeTlsDomain = secret.slice(17).toString() } else { - throw new Error('Unsupported secret') + throw new MtUnsupportedError('Unsupported secret') } } @@ -103,7 +106,7 @@ export class MtProxyTcpTransport extends BaseTcpTransport { connect(dc: tl.RawDcOption, testMode: boolean): void { if (this._state !== TransportState.Idle) { - throw new Error('Transport is not IDLE') + throw new MtcuteError('Transport is not IDLE') } if (this._packetCodec && this._currentDc?.id !== dc.id) { @@ -190,7 +193,7 @@ export class MtProxyTcpTransport extends BaseTcpTransport { } if (first.compare(first, 0, first.length) !== 0) { - throw new Error( + throw new MtSecurityError( 'First part of hello response is invalid', ) } @@ -218,7 +221,7 @@ export class MtProxyTcpTransport extends BaseTcpTransport { ) if (hash.compare(respRand) !== 0) { - throw new Error('Response hash is invalid') + throw new MtSecurityError('Response hash is invalid') } } diff --git a/packages/socks-proxy/index.ts b/packages/socks-proxy/index.ts index 1d3f4d07..8566e09d 100644 --- a/packages/socks-proxy/index.ts +++ b/packages/socks-proxy/index.ts @@ -9,6 +9,7 @@ import { assertNever, BaseTcpTransport, IntermediatePacketCodec, + MtArgumentError, tl, TransportState, } from '@mtcute/core' @@ -63,13 +64,13 @@ function writeIpv4(ip: string, buf: Buffer, offset: number): void { const parts = ip.split('.') if (parts.length !== 4) { - throw new Error('Invalid IPv4 address') + throw new MtArgumentError('Invalid IPv4 address') } for (let i = 0; i < 4; i++) { const n = parseInt(parts[i]) if (isNaN(n) || n < 0 || n > 255) { - throw new Error('Invalid IPv4 address') + throw new MtArgumentError('Invalid IPv4 address') } buf[offset + i] = n @@ -116,10 +117,14 @@ function buildSocks5Auth(username: string, password: string) { const passwordBuf = Buffer.from(password) if (usernameBuf.length > 255) { - throw new Error(`Too long username (${usernameBuf.length} > 255)`) + throw new MtArgumentError( + `Too long username (${usernameBuf.length} > 255)`, + ) } if (passwordBuf.length > 255) { - throw new Error(`Too long password (${passwordBuf.length} > 255)`) + throw new MtArgumentError( + `Too long password (${passwordBuf.length} > 255)`, + ) } const buf = Buffer.alloc(3 + usernameBuf.length + passwordBuf.length) @@ -138,14 +143,14 @@ function writeIpv6(ip: string, buf: Buffer, offset: number): void { const parts = ip.split(':') if (parts.length !== 8) { - throw new Error('Invalid IPv6 address') + throw new MtArgumentError('Invalid IPv6 address') } for (let i = 0, j = offset; i < 8; i++, j += 2) { const n = parseInt(parts[i]) if (isNaN(n) || n < 0 || n > 0xffff) { - throw new Error('Invalid IPv6 address') + throw new MtArgumentError('Invalid IPv6 address') } buf.writeUInt16BE(n, j) @@ -215,7 +220,7 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport { connect(dc: tl.RawDcOption): void { if (this._state !== TransportState.Idle) { - throw new Error('Transport is not IDLE') + throw new MtArgumentError('Transport is not IDLE') } if (!this.packetCodecInitialized) {