diff --git a/.prettierrc b/.prettierrc index 12c574c7..54a4d33d 100644 --- a/.prettierrc +++ b/.prettierrc @@ -6,14 +6,14 @@ "insertPragma": false, "jsxBracketSameLine": false, "jsxSingleQuote": false, - "printWidth": 80, + "printWidth": 120, "proseWrap": "preserve", "quoteProps": "as-needed", "requirePragma": false, "semi": false, "singleQuote": true, "tabWidth": 4, - "trailingComma": "es5", + "trailingComma": "all", "useTabs": false, "vueIndentScriptAndStyle": false } diff --git a/packages/client/src/client.ts b/packages/client/src/client.ts index 495a6f19..aeecc2f4 100644 --- a/packages/client/src/client.ts +++ b/packages/client/src/client.ts @@ -2,19 +2,8 @@ /* THIS FILE WAS AUTO-GENERATED */ import { Readable } from 'stream' -import { - BaseTelegramClient, - BaseTelegramClientOptions, - MaybeArray, - MaybeAsync, -} from '@mtcute/core' -import { - AsyncLock, - ConditionVariable, - Deque, - Logger, - SortedLinkedList, -} from '@mtcute/core/utils' +import { BaseTelegramClient, BaseTelegramClientOptions, MaybeArray, MaybeAsync } from '@mtcute/core' +import { AsyncLock, ConditionVariable, Deque, Logger, SortedLinkedList } from '@mtcute/core/utils' import { tdFileId } from '@mtcute/file-id' import { tl } from '@mtcute/tl' @@ -38,10 +27,7 @@ import { answerPreCheckoutQuery } from './methods/bots/answer-pre-checkout-query import { deleteMyCommands } from './methods/bots/delete-my-commands' import { getBotMenuButton } from './methods/bots/get-bot-menu-button' import { getCallbackAnswer } from './methods/bots/get-callback-answer' -import { - getGameHighScores, - getInlineGameHighScores, -} from './methods/bots/get-game-high-scores' +import { getGameHighScores, getInlineGameHighScores } from './methods/bots/get-game-high-scores' import { getMyCommands } from './methods/bots/get-my-commands' import { _normalizeCommandScope } from './methods/bots/normalize-command-scope' import { setBotMenuButton } from './methods/bots/set-bot-menu-button' @@ -122,10 +108,7 @@ import { editInlineMessage } from './methods/messages/edit-inline-message' import { editMessage } from './methods/messages/edit-message' import { _findMessageInUpdate } from './methods/messages/find-in-update' import { forwardMessages } from './methods/messages/forward-messages' -import { - _getDiscussionMessage, - getDiscussionMessage, -} from './methods/messages/get-discussion-message' +import { _getDiscussionMessage, getDiscussionMessage } from './methods/messages/get-discussion-message' import { getHistory } from './methods/messages/get-history' import { getMessageGroup } from './methods/messages/get-message-group' import { getMessageReactions } from './methods/messages/get-message-reactions' @@ -160,11 +143,7 @@ import { } from './methods/parse-modes/parse-modes' import { changeCloudPassword } from './methods/pasword/change-cloud-password' import { enableCloudPassword } from './methods/pasword/enable-cloud-password' -import { - cancelPasswordEmail, - resendPasswordEmail, - verifyPasswordEmail, -} from './methods/pasword/password-email' +import { cancelPasswordEmail, resendPasswordEmail, verifyPasswordEmail } from './methods/pasword/password-email' import { removeCloudPassword } from './methods/pasword/remove-cloud-password' import { addStickerToSet } from './methods/stickers/add-sticker-to-set' import { createStickerSet } from './methods/stickers/create-sticker-set' @@ -292,13 +271,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param name Event name * @param handler Raw update handler */ - on( - name: 'raw_update', - handler: ( - upd: tl.TypeUpdate | tl.TypeMessage, - peers: PeersIndex - ) => void - ): this + on(name: 'raw_update', handler: (upd: tl.TypeUpdate | tl.TypeMessage, peers: PeersIndex) => void): this /** * Register a parsed update handler * @@ -326,10 +299,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param name Event name * @param handler Delete message handler */ - on( - name: 'delete_message', - handler: (upd: DeleteMessageUpdate) => void - ): this + on(name: 'delete_message', handler: (upd: DeleteMessageUpdate) => void): this /** * Register a chat member update handler * @@ -350,10 +320,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param name Event name * @param handler Chosen inline result handler */ - on( - name: 'chosen_inline_result', - handler: (upd: ChosenInlineResult) => void - ): this + on(name: 'chosen_inline_result', handler: (upd: ChosenInlineResult) => void): this /** * Register a callback query handler * @@ -409,30 +376,21 @@ export interface TelegramClient extends BaseTelegramClient { * @param name Event name * @param handler Bot chat join request handler */ - on( - name: 'bot_chat_join_request', - handler: (upd: BotChatJoinRequestUpdate) => void - ): this + on(name: 'bot_chat_join_request', handler: (upd: BotChatJoinRequestUpdate) => void): this /** * Register a chat join request handler * * @param name Event name * @param handler Chat join request handler */ - on( - name: 'chat_join_request', - handler: (upd: ChatJoinRequestUpdate) => void - ): this + on(name: 'chat_join_request', handler: (upd: ChatJoinRequestUpdate) => void): this /** * Register a pre checkout query handler * * @param name Event name * @param handler Pre checkout query handler */ - on( - name: 'pre_checkout_query', - handler: (upd: PreCheckoutQuery) => void - ): this + on(name: 'pre_checkout_query', handler: (upd: PreCheckoutQuery) => void): this /** * Accept the given TOS * @@ -491,10 +449,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param params Parameters to be passed to {@link TelegramClient.start} * @param then Function to be called after {@link TelegramClient.start} returns */ - run( - params: Parameters[0], - then?: (user: User) => void | Promise - ): void + run(params: Parameters[0], then?: (user: User) => void | Promise): void /** * Send the confirmation code to the given phone number * @@ -530,11 +485,7 @@ export interface TelegramClient extends BaseTelegramClient { * @throws BadRequestError In case the arguments are invalid * @throws SessionPasswordNeededError In case a password is needed to sign in */ - signIn( - phone: string, - phoneCodeHash: string, - phoneCode: string - ): Promise + signIn(phone: string, phoneCodeHash: string, phoneCode: string): Promise /** * Register a new user in Telegram. * @@ -543,12 +494,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param firstName New user's first name * @param lastName (default: `''`) New user's last name */ - signUp( - phone: string, - phoneCodeHash: string, - firstName: string, - lastName?: string - ): Promise + signUp(phone: string, phoneCodeHash: string, firstName: string, lastName?: string): Promise /** * Utility function to quickly authorize on test DC * using a [Test phone number](https://core.telegram.org/api/auth#test-phone-numbers), @@ -759,7 +705,7 @@ export interface TelegramClient extends BaseTelegramClient { * with a deep-link parameter. */ url?: string - } + }, ): Promise /** * Answer an inline query. @@ -849,7 +795,7 @@ export interface TelegramClient extends BaseTelegramClient { * entities, only the messages that are sent once a result is clicked. */ parseMode?: string | null - } + }, ): Promise /** * Answer a pre-checkout query. @@ -918,7 +864,7 @@ export interface TelegramClient extends BaseTelegramClient { * bot, it is checked by Telegram. */ password?: string - } + }, ): Promise /** * Get high scores of a game @@ -927,11 +873,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param message ID of the message containing the game * @param userId ID of the user to find high scores for */ - getGameHighScores( - chatId: InputPeerLike, - message: number, - userId?: InputPeerLike - ): Promise + getGameHighScores(chatId: InputPeerLike, message: number, userId?: InputPeerLike): Promise /** * Get high scores of a game from an inline message * @@ -940,7 +882,7 @@ export interface TelegramClient extends BaseTelegramClient { */ getInlineGameHighScores( messageId: string | tl.TypeInputBotInlineMessageID, - userId?: InputPeerLike + userId?: InputPeerLike, ): Promise /** * Get a list of current bot's commands for the given command scope @@ -964,16 +906,13 @@ export interface TelegramClient extends BaseTelegramClient { }): Promise _normalizeCommandScope( - scope: tl.TypeBotCommandScope | BotCommands.IntermediateScope + scope: tl.TypeBotCommandScope | BotCommands.IntermediateScope, ): Promise /** * Sets a menu button for the given user. * */ - setBotMenuButton( - user: InputPeerLike, - button: tl.TypeBotMenuButton - ): Promise + setBotMenuButton(user: InputPeerLike, button: tl.TypeBotMenuButton): Promise /** * Set a score of a user in a game * @@ -1058,10 +997,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param target Whether to target groups or channels. * @param rights The default chat permissions. */ - setMyDefaultRights( - target: 'channel' | 'group', - rights: Omit - ): Promise + setMyDefaultRights(target: 'channel' | 'group', rights: Omit): Promise /** * Add new members to a group, supergroup or channel. * @@ -1072,11 +1008,7 @@ export interface TelegramClient extends BaseTelegramClient { * Number of old messages to be forwarded (0-100). * Only applicable to legacy groups, ignored for supergroups and channels */ - addChatMembers( - chatId: InputPeerLike, - users: MaybeArray, - forwardCount?: number - ): Promise + addChatMembers(chatId: InputPeerLike, users: MaybeArray, forwardCount?: number): Promise /** * Archive one or more chats * @@ -1092,10 +1024,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param userId User ID * @returns Service message about removed user, if one was generated. */ - banChatMember( - chatId: InputPeerLike, - userId: InputPeerLike - ): Promise + banChatMember(chatId: InputPeerLike, userId: InputPeerLike): Promise /** * Create a new broadcast channel * @@ -1166,21 +1095,14 @@ export interface TelegramClient extends BaseTelegramClient { * but they are in fact different flags in TL object. * @param maxId (default: `0`) Maximum ID of message to delete. Defaults to 0 (remove all messages) */ - deleteHistory( - chat: InputPeerLike, - mode?: 'delete' | 'clear' | 'revoke', - maxId?: number - ): Promise + deleteHistory(chat: InputPeerLike, mode?: 'delete' | 'clear' | 'revoke', maxId?: number): Promise /** * Delete all messages of a user (or channel) in a supergroup * * @param chatId Chat ID * @param participantId User/channel ID */ - deleteUserHistory( - chatId: InputPeerLike, - participantId: InputPeerLike - ): Promise + deleteUserHistory(chatId: InputPeerLike, participantId: InputPeerLike): Promise /** * Edit supergroup/channel admin rights of a user. * @@ -1193,7 +1115,7 @@ export interface TelegramClient extends BaseTelegramClient { chatId: InputPeerLike, userId: InputPeerLike, rights: Omit, - rank?: string + rank?: string, ): Promise /** * Get chat event log ("Recent actions" in official @@ -1244,9 +1166,7 @@ export interface TelegramClient extends BaseTelegramClient { * and when passing one or more action types, * they will be filtered locally. */ - filters?: - | tl.TypeChannelAdminLogEventsFilter - | MaybeArray['type']> + filters?: tl.TypeChannelAdminLogEventsFilter | MaybeArray['type']> /** * Limit the number of events returned. @@ -1261,7 +1181,7 @@ export interface TelegramClient extends BaseTelegramClient { * Defaults to `100` */ chunkSize?: number - } + }, ): AsyncIterableIterator /** * Get information about a single chat member @@ -1270,10 +1190,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param userId User ID, username, phone number, `"me"` or `"self"` * @throws UserNotParticipantError In case given user is not a participant of a given chat */ - getChatMember( - chatId: InputPeerLike, - userId: InputPeerLike - ): Promise + getChatMember(chatId: InputPeerLike, userId: InputPeerLike): Promise /** * Get a chunk of members of some chat. * @@ -1317,16 +1234,8 @@ export interface TelegramClient extends BaseTelegramClient { * * Only used for channels and supergroups. Defaults to `recent` */ - type?: - | 'all' - | 'banned' - | 'restricted' - | 'bots' - | 'recent' - | 'admins' - | 'contacts' - | 'mention' - } + type?: 'all' | 'banned' | 'restricted' | 'bots' | 'recent' | 'admins' | 'contacts' | 'mention' + }, ): Promise> /** * Get preview information about a private chat. @@ -1383,7 +1292,7 @@ export interface TelegramClient extends BaseTelegramClient { * Defaults to `200` */ chunkSize?: number - } + }, ): AsyncIterableIterator /** * Join a channel or supergroup @@ -1439,7 +1348,7 @@ export interface TelegramClient extends BaseTelegramClient { chatId: InputPeerLike, userId: InputPeerLike, restrictions: Omit, - until?: number | Date + until?: number | Date, ): Promise /** * Save or delete a draft message associated with some chat @@ -1447,10 +1356,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param chatId ID of the chat, its username, phone or `"me"` or `"self"` * @param draft Draft message, or `null` to delete. */ - saveDraft( - chatId: InputPeerLike, - draft: null | Omit - ): Promise + saveDraft(chatId: InputPeerLike, draft: null | Omit): Promise /** * Change default chat permissions for all members. * @@ -1465,7 +1371,7 @@ export interface TelegramClient extends BaseTelegramClient { */ setChatDefaultPermissions( chatId: InputPeerLike, - restrictions: Omit + restrictions: Omit, ): Promise /** * Change chat description @@ -1475,10 +1381,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param chatId Chat ID or username * @param description New chat description, 0-255 characters */ - setChatDescription( - chatId: InputPeerLike, - description: string - ): Promise + setChatDescription(chatId: InputPeerLike, description: string): Promise /** * Set a new chat photo or video. * @@ -1495,7 +1398,7 @@ export interface TelegramClient extends BaseTelegramClient { chatId: InputPeerLike, type: 'photo' | 'video', media: InputFileLike, - previewSec?: number + previewSec?: number, ): Promise /** * Change chat title @@ -1514,10 +1417,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param chatId Chat ID or current username * @param username New username, or `null` to remove */ - setChatUsername( - chatId: InputPeerLike, - username: string | null - ): Promise + setChatUsername(chatId: InputPeerLike, username: string | null): Promise /** * Set supergroup's slow mode interval. * @@ -1560,10 +1460,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param chatId Chat ID * @param userId User ID */ - unrestrictChatMember( - chatId: InputPeerLike, - userId: InputPeerLike - ): Promise + unrestrictChatMember(chatId: InputPeerLike, userId: InputPeerLike): Promise /** * Add an existing Telegram user as a contact * @@ -1593,7 +1490,7 @@ export interface TelegramClient extends BaseTelegramClient { * with the newly created contact (defaults to `false`) */ sharePhone?: boolean - } + }, ): Promise /** * Delete a single contact from your Telegram contacts list @@ -1623,7 +1520,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param contacts List of contacts */ importContacts( - contacts: PartialOnly, 'clientId'>[] + contacts: PartialOnly, 'clientId'>[], ): Promise _pushConversationMessage(msg: Message, incoming?: boolean): void @@ -1636,9 +1533,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param folder Parameters for the folder * @returns Newly created folder */ - createFolder( - folder: PartialExcept - ): Promise + createFolder(folder: PartialExcept): Promise /** * Delete a folder by its ID * @@ -1658,7 +1553,7 @@ export interface TelegramClient extends BaseTelegramClient { */ editFolder( folder: tl.RawDialogFilter | number | string, - modification: Partial> + modification: Partial>, ): Promise /** * Find a folder by its parameter. @@ -1669,11 +1564,7 @@ export interface TelegramClient extends BaseTelegramClient { * * @param params Search parameters. At least one must be set. */ - findFolder(params: { - title?: string - emoji?: string - id?: number - }): Promise + findFolder(params: { title?: string; emoji?: string; id?: number }): Promise /** * Iterate over dialogs. * @@ -1797,9 +1688,7 @@ export interface TelegramClient extends BaseTelegramClient { */ getPeerDialogs(peers: InputPeerLike[]): Promise - _parseDialogs( - res: tl.messages.TypeDialogs | tl.messages.TypePeerDialogs - ): Dialog[] + _parseDialogs(res: tl.messages.TypeDialogs | tl.messages.TypePeerDialogs): Dialog[] /** * Reorder folders * @@ -1823,10 +1712,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param filename Local file name to which the remote file will be downloaded * @param params File download parameters */ - downloadToFile( - filename: string, - params: FileDownloadParameters - ): Promise + downloadToFile(filename: string, params: FileDownloadParameters): Promise /** * Download a file and return it as an iterable, which yields file contents * in chunks of a given size. Order of the chunks is guaranteed to be @@ -1834,9 +1720,7 @@ export interface TelegramClient extends BaseTelegramClient { * * @param params Download parameters */ - downloadAsIterable( - params: FileDownloadParameters - ): AsyncIterableIterator + downloadAsIterable(params: FileDownloadParameters): AsyncIterableIterator /** * Download a file and return it as a Node readable stream, * streaming file contents. @@ -1848,7 +1732,7 @@ export interface TelegramClient extends BaseTelegramClient { file: InputFileLike | tl.TypeInputDocument, params: { progressCallback?: (uploaded: number, total: number) => void - } + }, ): Promise /** * Normalize a {@link InputFileLike} to `InputFile`, @@ -1862,7 +1746,7 @@ export interface TelegramClient extends BaseTelegramClient { fileName?: string fileSize?: number fileMime?: string - } + }, ): Promise /** * Normalize an {@link InputMediaLike} to `InputMedia`, @@ -1876,7 +1760,7 @@ export interface TelegramClient extends BaseTelegramClient { progressCallback?: (uploaded: number, total: number) => void uploadPeer?: tl.TypeInputPeer }, - uploadMedia?: boolean + uploadMedia?: boolean, ): Promise /** * Upload a file to Telegram servers, without actually @@ -1958,7 +1842,7 @@ export interface TelegramClient extends BaseTelegramClient { params?: { peer?: InputPeerLike progressCallback?: (uploaded: number, total: number) => void - } + }, ): Promise> /** * Create an additional invite link for the chat. @@ -1990,7 +1874,7 @@ export interface TelegramClient extends BaseTelegramClient { * approved by an admin */ withApproval?: boolean - } + }, ): Promise /** * Edit an invite link. You can only edit non-primary @@ -2026,7 +1910,7 @@ export interface TelegramClient extends BaseTelegramClient { * approved by an admin */ withApproval?: boolean - } + }, ): Promise /** * Generate a new primary invite link for a chat, @@ -2071,7 +1955,7 @@ export interface TelegramClient extends BaseTelegramClient { * Doesn't work when {@link link} is set (Telegram limitation) */ requestedSearch?: string - } + }, ): AsyncIterableIterator /** * Get detailed information about an invite link @@ -2112,7 +1996,7 @@ export interface TelegramClient extends BaseTelegramClient { * Defaults to `100` */ chunkSize?: number - } + }, ): AsyncIterableIterator /** * Get primary invite link of a chat @@ -2127,11 +2011,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param action Whether to approve or deny the join requests * @param link Invite link to target */ - hideAllJoinRequests( - peer: InputPeerLike, - action: 'approve' | 'deny', - link?: string - ): Promise + hideAllJoinRequests(peer: InputPeerLike, action: 'approve' | 'deny', link?: string): Promise /** * Approve or deny join request to a chat. * @@ -2139,11 +2019,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param user User ID * @param action Whether to approve or deny the join request */ - hideJoinRequest( - peer: InputPeerLike, - user: InputPeerLike, - action: 'approve' | 'deny' - ): Promise + hideJoinRequest(peer: InputPeerLike, user: InputPeerLike, action: 'approve' | 'deny'): Promise /** * Revoke an invite link. * @@ -2154,10 +2030,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param link Invite link to revoke * @returns If `link` is a primary invite, newly generated invite link, otherwise the revoked link */ - revokeInviteLink( - chatId: InputPeerLike, - link: string - ): Promise + revokeInviteLink(chatId: InputPeerLike, link: string): Promise /** * Close a poll sent by you. * @@ -2176,21 +2049,14 @@ export interface TelegramClient extends BaseTelegramClient { * @param revoke (default: `true`) Whether to "revoke" (i.e. delete for both sides). * Only used for chats and private chats. */ - deleteMessages( - chatId: InputPeerLike, - ids: MaybeArray, - revoke?: boolean - ): Promise + deleteMessages(chatId: InputPeerLike, ids: MaybeArray, revoke?: boolean): Promise /** * Delete scheduled messages. * * @param chatId Chat's marked ID, its username, phone or `"me"` or `"self"`. * @param ids Message(s) ID(s) to delete. */ - deleteScheduledMessages( - chatId: InputPeerLike, - ids: MaybeArray - ): Promise + deleteScheduledMessages(chatId: InputPeerLike, ids: MaybeArray): Promise /** * Edit sent inline message text, media and reply markup. * @@ -2250,7 +2116,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param total Total file size in bytes */ progressCallback?: (uploaded: number, total: number) => void - } + }, ): Promise /** * Edit message text, media, reply markup and schedule date. @@ -2317,7 +2183,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param total Total file size in bytes */ progressCallback?: (uploaded: number, total: number) => void - } + }, ): Promise _findMessageInUpdate(res: tl.TypeUpdates, isEdit?: boolean): Message @@ -2410,7 +2276,7 @@ export interface TelegramClient extends BaseTelegramClient { * have content protection. */ forbidForwards?: boolean - } + }, ): Promise /** * Forward one or more messages, optionally including a caption message. @@ -2504,13 +2370,10 @@ export interface TelegramClient extends BaseTelegramClient { * have content protection. */ forbidForwards?: boolean - } + }, ): Promise> - _getDiscussionMessage( - peer: InputPeerLike, - message: number - ): Promise<[tl.TypeInputPeer, number]> + _getDiscussionMessage(peer: InputPeerLike, message: number): Promise<[tl.TypeInputPeer, number]> // public version of the same method because why not /** * Get discussion message for some channel post. @@ -2526,10 +2389,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param peer Channel where the post was found * @param message ID of the channel post */ - getDiscussionMessage( - peer: InputPeerLike, - message: number - ): Promise + getDiscussionMessage(peer: InputPeerLike, message: number): Promise /** * Iterate through a chat history sequentially. * @@ -2595,7 +2455,7 @@ export interface TelegramClient extends BaseTelegramClient { * Defaults to `100` */ chunkSize?: number - } + }, ): AsyncIterableIterator /** * Get all messages inside of a message group @@ -2615,10 +2475,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param messages Message ID * @returns Reactions to the corresponding message, or `null` if there are none */ - getMessageReactions( - chatId: InputPeerLike, - messages: number - ): Promise + getMessageReactions(chatId: InputPeerLike, messages: number): Promise /** * Get reactions to messages. * @@ -2630,10 +2487,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param messages Message IDs * @returns Reactions to corresponding messages, or `null` if there are none */ - getMessageReactions( - chatId: InputPeerLike, - messages: number[] - ): Promise<(MessageReactions | null)[]> + getMessageReactions(chatId: InputPeerLike, messages: number[]): Promise<(MessageReactions | null)[]> /** * Get a single message from PM or legacy group by its ID. * For channels, use {@link getMessages}. @@ -2646,10 +2500,7 @@ export interface TelegramClient extends BaseTelegramClient { * Whether the reply to a given message should be fetched * (i.e. `getMessages(msg.chat.id, msg.id, true).id === msg.replyToMessageId`) */ - getMessagesUnsafe( - messageId: number, - fromReply?: boolean - ): Promise + getMessagesUnsafe(messageId: number, fromReply?: boolean): Promise /** * Get messages from PM or legacy group by their IDs. * For channels, use {@link getMessages}. @@ -2665,10 +2516,7 @@ export interface TelegramClient extends BaseTelegramClient { * Whether the reply to a given message should be fetched * (i.e. `getMessages(msg.chat.id, msg.id, true).id === msg.replyToMessageId`) */ - getMessagesUnsafe( - messageIds: number[], - fromReply?: boolean - ): Promise<(Message | null)[]> + getMessagesUnsafe(messageIds: number[], fromReply?: boolean): Promise<(Message | null)[]> /** * Get a single message in chat by its ID * @@ -2678,11 +2526,7 @@ export interface TelegramClient extends BaseTelegramClient { * Whether the reply to a given message should be fetched * (i.e. `getMessages(msg.chat.id, msg.id, true).id === msg.replyToMessageId`) */ - getMessages( - chatId: InputPeerLike, - messageId: number, - fromReply?: boolean - ): Promise + getMessages(chatId: InputPeerLike, messageId: number, fromReply?: boolean): Promise /** * Get messages in chat by their IDs * @@ -2695,11 +2539,7 @@ export interface TelegramClient extends BaseTelegramClient { * Whether the reply to a given message should be fetched * (i.e. `getMessages(msg.chat.id, msg.id, true).id === msg.replyToMessageId`) */ - getMessages( - chatId: InputPeerLike, - messageIds: number[], - fromReply?: boolean - ): Promise<(Message | null)[]> + getMessages(chatId: InputPeerLike, messageIds: number[], fromReply?: boolean): Promise<(Message | null)[]> /** * Get users who have reacted to the message. * @@ -2734,7 +2574,7 @@ export interface TelegramClient extends BaseTelegramClient { * Defaults to `100` */ chunkSize?: number - } + }, ): AsyncIterableIterator /** * Get a single scheduled message in chat by its ID @@ -2742,10 +2582,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param chatId Chat's marked ID, its username, phone or `"me"` or `"self"` * @param messageId Scheduled message ID */ - getScheduledMessages( - chatId: InputPeerLike, - messageId: number - ): Promise + getScheduledMessages(chatId: InputPeerLike, messageId: number): Promise /** * Get scheduled messages in chat by their IDs * @@ -2755,15 +2592,12 @@ export interface TelegramClient extends BaseTelegramClient { * @param chatId Chat's marked ID, its username, phone or `"me"` or `"self"` * @param messageIds Scheduled messages IDs */ - getScheduledMessages( - chatId: InputPeerLike, - messageIds: number[] - ): Promise<(Message | null)[]> + getScheduledMessages(chatId: InputPeerLike, messageIds: number[]): Promise<(Message | null)[]> _parseEntities( text?: string | FormattedString, mode?: string | null, - entities?: tl.TypeMessageEntity[] + entities?: tl.TypeMessageEntity[], ): Promise<[string, tl.TypeMessageEntity[] | undefined]> /** * Pin a message in a group, supergroup, channel or PM. @@ -2776,12 +2610,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param notify (default: `false`) Whether to send a notification (only for legacy groups and supergroups) * @param bothSides (default: `false`) Whether to pin for both sides (only for private chats) */ - pinMessage( - chatId: InputPeerLike, - messageId: number, - notify?: boolean, - bothSides?: boolean - ): Promise + pinMessage(chatId: InputPeerLike, messageId: number, notify?: boolean, bothSides?: boolean): Promise /** * Mark chat history as read. * @@ -2789,11 +2618,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param message (default: `0`) Message up until which to read history (by default everything is read) * @param clearMentions (default: `false`) Whether to also clear all mentions in the chat */ - readHistory( - chatId: InputPeerLike, - message?: number, - clearMentions?: boolean - ): Promise + readHistory(chatId: InputPeerLike, message?: number, clearMentions?: boolean): Promise /** * Mark all reactions in chat as read. * @@ -2935,7 +2760,7 @@ export interface TelegramClient extends BaseTelegramClient { * Defaults to `100` */ chunkSize?: number - } + }, ): AsyncIterableIterator /** * Copy a message (i.e. send the same message, @@ -3025,7 +2850,7 @@ export interface TelegramClient extends BaseTelegramClient { * Defaults to `false` */ clearDraft?: boolean - } + }, ): Promise /** * Send a group of media. @@ -3098,11 +2923,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param uploaded Number of bytes already uploaded * @param total Total file size */ - progressCallback?: ( - index: number, - uploaded: number, - total: number - ) => void + progressCallback?: (index: number, uploaded: number, total: number) => void /** * Whether to clear draft after sending this message. @@ -3123,7 +2944,7 @@ export interface TelegramClient extends BaseTelegramClient { * Peer to use when sending the message. */ sendAs?: InputPeerLike - } + }, ): Promise /** * Send a single media (a photo or a document-based media) @@ -3238,7 +3059,7 @@ export interface TelegramClient extends BaseTelegramClient { * Peer to use when sending the message. */ sendAs?: InputPeerLike - } + }, ): Promise /** * Send or remove a reaction. @@ -3253,7 +3074,7 @@ export interface TelegramClient extends BaseTelegramClient { chatId: InputPeerLike, message: number, emoji: string | tl.Long | null, - big?: boolean + big?: boolean, ): Promise /** * Send s previously scheduled message. @@ -3373,7 +3194,7 @@ export interface TelegramClient extends BaseTelegramClient { * Peer to use when sending the message. */ sendAs?: InputPeerLike - } + }, ): Promise /** * Sends a current user/bot typing event @@ -3400,7 +3221,7 @@ export interface TelegramClient extends BaseTelegramClient { * For comment threads, ID of the thread (i.e. top message) */ threadId?: number - } + }, ): Promise /** * Send or retract a vote in a poll. @@ -3413,11 +3234,7 @@ export interface TelegramClient extends BaseTelegramClient { * representing them. In case of indexes, the poll will first * be requested from the server. */ - sendVote( - chatId: InputPeerLike, - message: number, - options: null | MaybeArray - ): Promise + sendVote(chatId: InputPeerLike, message: number, options: null | MaybeArray): Promise /** * Translate message text to a given language. * @@ -3432,7 +3249,7 @@ export interface TelegramClient extends BaseTelegramClient { translateMessage( chatId: InputPeerLike, messageId: number, - toLanguage: string + toLanguage: string, ): Promise<[string, MessageEntity[]] | null> /** * Translate text to a given language. @@ -3466,9 +3283,7 @@ export interface TelegramClient extends BaseTelegramClient { * * @param params Takeout session parameters */ - initTakeoutSession( - params: Omit - ): Promise + initTakeoutSession(params: Omit): Promise /** * Register a given {@link IMessageEntityParser} as a parse mode * for messages. When this method is first called, given parse @@ -3509,11 +3324,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param newPassword New password as plaintext * @param hint Hint for the new password */ - changeCloudPassword( - currentPassword: string, - newPassword: string, - hint?: string - ): Promise + changeCloudPassword(currentPassword: string, newPassword: string, hint?: string): Promise /** * Enable 2FA password on your account * @@ -3526,11 +3337,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param hint Hint for the new password * @param email Recovery email */ - enableCloudPassword( - password: string, - hint?: string, - email?: string - ): Promise + enableCloudPassword(password: string, hint?: string, email?: string): Promise /** * Verify an email to use as 2FA recovery method * @@ -3575,7 +3382,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param total Total file size */ progressCallback?: (uploaded: number, total: number) => void - } + }, ): Promise /** * Create a new sticker set. @@ -3648,11 +3455,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param uploaded Number of bytes uploaded * @param total Total file size */ - progressCallback?: ( - idx: number, - uploaded: number, - total: number - ) => void + progressCallback?: (idx: number, uploaded: number, total: number) => void }): Promise /** * Delete a sticker from a sticker set @@ -3666,10 +3469,7 @@ export interface TelegramClient extends BaseTelegramClient { * @returns Modfiied sticker set */ deleteStickerFromSet( - sticker: - | string - | tdFileId.RawFullRemoteFileLocation - | tl.TypeInputDocument + sticker: string | tdFileId.RawFullRemoteFileLocation | tl.TypeInputDocument, ): Promise /** * Get custom emoji stickers by their IDs @@ -3692,9 +3492,7 @@ export interface TelegramClient extends BaseTelegramClient { * * @param id Sticker pack short name, dice emoji, `"emoji"` for animated emojis or input ID */ - getStickerSet( - id: string | { dice: string } | tl.TypeInputStickerSet - ): Promise + getStickerSet(id: string | { dice: string } | tl.TypeInputStickerSet): Promise /** * Move a sticker in a sticker set * to another position @@ -3709,11 +3507,8 @@ export interface TelegramClient extends BaseTelegramClient { * @returns Modfiied sticker set */ moveStickerInSet( - sticker: - | string - | tdFileId.RawFullRemoteFileLocation - | tl.TypeInputDocument, - position: number + sticker: string | tdFileId.RawFullRemoteFileLocation | tl.TypeInputDocument, + position: number, ): Promise /** * Set sticker set thumbnail @@ -3734,7 +3529,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param total Total file size */ progressCallback?: (uploaded: number, total: number) => void - } + }, ): Promise /** * Enable RPS meter. @@ -3792,10 +3587,7 @@ export interface TelegramClient extends BaseTelegramClient { _onStop(): void _saveStorage(afterImport?: boolean): Promise - _dispatchUpdate( - update: tl.TypeUpdate | tl.TypeMessage, - peers: PeersIndex - ): void + _dispatchUpdate(update: tl.TypeUpdate | tl.TypeMessage, peers: PeersIndex): void _handleUpdate(update: tl.TypeUpdates, noDispatch?: boolean): void /** * Catch up with the server by loading missed updates. @@ -3819,9 +3611,7 @@ export interface TelegramClient extends BaseTelegramClient { * * @param ids ID(s) of the photos. Can be file IDs or raw TL objects */ - deleteProfilePhotos( - ids: MaybeArray - ): Promise + deleteProfilePhotos(ids: MaybeArray): Promise /** * Get a list of common chats you have with a given user * @@ -3864,7 +3654,7 @@ export interface TelegramClient extends BaseTelegramClient { * Defaults to `100` */ limit?: number - } + }, ): Promise /** * Get information about a single user. @@ -3916,7 +3706,7 @@ export interface TelegramClient extends BaseTelegramClient { * with IDs less than the set one */ maxId?: tl.Long - } + }, ): AsyncIterableIterator /** * Get multiple `InputPeer`s at once, @@ -3928,11 +3718,9 @@ export interface TelegramClient extends BaseTelegramClient { * @param peerIds Peer Ids * @param normalizer Normalization function */ - resolvePeerMany< - T extends tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel - >( + resolvePeerMany( peerIds: InputPeerLike[], - normalizer: (obj: tl.TypeInputPeer) => T | null + normalizer: (obj: tl.TypeInputPeer) => T | null, ): Promise /** * Get multiple `InputPeer`s at once. @@ -3949,10 +3737,7 @@ export interface TelegramClient extends BaseTelegramClient { * @param peerId The peer identifier that you want to extract the `InputPeer` from. * @param force (default: `false`) Whether to force re-fetch the peer from the server */ - resolvePeer( - peerId: InputPeerLike, - force?: boolean - ): Promise + resolvePeer(peerId: InputPeerLike, force?: boolean): Promise /** * Change user status to offline or online * @@ -3973,7 +3758,7 @@ export interface TelegramClient extends BaseTelegramClient { setProfilePhoto( type: 'photo' | 'video', media: InputFileLike | tl.TypeInputPhoto, - previewSec?: number + previewSec?: number, ): Promise /** * Unblock a user @@ -4060,21 +3845,11 @@ export class TelegramClient extends BaseTelegramClient { this._updatesLoopActive = false this._updatesLoopCv = new ConditionVariable() - this._pendingUpdateContainers = new SortedLinkedList( - (a, b) => a.seqStart - b.seqStart, - ) - this._pendingPtsUpdates = new SortedLinkedList( - (a, b) => a.ptsBefore! - b.ptsBefore!, - ) - this._pendingPtsUpdatesPostponed = new SortedLinkedList( - (a, b) => a.ptsBefore! - b.ptsBefore!, - ) - this._pendingQtsUpdates = new SortedLinkedList( - (a, b) => a.qtsBefore! - b.qtsBefore!, - ) - this._pendingQtsUpdatesPostponed = new SortedLinkedList( - (a, b) => a.qtsBefore! - b.qtsBefore!, - ) + this._pendingUpdateContainers = new SortedLinkedList((a, b) => a.seqStart - b.seqStart) + this._pendingPtsUpdates = new SortedLinkedList((a, b) => a.ptsBefore! - b.ptsBefore!) + this._pendingPtsUpdatesPostponed = new SortedLinkedList((a, b) => a.ptsBefore! - b.ptsBefore!) + this._pendingQtsUpdates = new SortedLinkedList((a, b) => a.qtsBefore! - b.qtsBefore!) + this._pendingQtsUpdatesPostponed = new SortedLinkedList((a, b) => a.qtsBefore! - b.qtsBefore!) this._pendingUnorderedUpdates = new Deque() this._updLock = new AsyncLock() diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index c7680031..1060f9bb 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -3,10 +3,4 @@ export * from './client' export * from './types' export * from './utils/peer-utils' export { createDummyUpdate } from './utils/updates-utils' -export { - assertNever, - JsonFileStorage, - LocalstorageStorage, - MemoryStorage, - tl, -} from '@mtcute/core' +export { assertNever, JsonFileStorage, LocalstorageStorage, MemoryStorage, tl } from '@mtcute/core' diff --git a/packages/client/src/methods/_imports.ts b/packages/client/src/methods/_imports.ts index 2a26803c..c17188d6 100644 --- a/packages/client/src/methods/_imports.ts +++ b/packages/client/src/methods/_imports.ts @@ -5,13 +5,7 @@ import { Readable } from 'stream' // @copy import { MaybeArray, MaybeAsync } from '@mtcute/core' // @copy -import { - AsyncLock, - ConditionVariable, - Deque, - Logger, - SortedLinkedList, -} from '@mtcute/core/utils' +import { AsyncLock, ConditionVariable, Deque, Logger, SortedLinkedList } from '@mtcute/core/utils' // @copy import { tdFileId } from '@mtcute/file-id' diff --git a/packages/client/src/methods/auth/accept-tos.ts b/packages/client/src/methods/auth/accept-tos.ts index 67763985..1c6af305 100644 --- a/packages/client/src/methods/auth/accept-tos.ts +++ b/packages/client/src/methods/auth/accept-tos.ts @@ -8,10 +8,7 @@ import { TelegramClient } from '../../client' * @param tosId TOS id * @internal */ -export async function acceptTos( - this: TelegramClient, - tosId: string, -): Promise { +export async function acceptTos(this: TelegramClient, tosId: string): Promise { const res = await this.call({ _: 'help.acceptTermsOfService', id: { @@ -21,11 +18,7 @@ export async function acceptTos( }) if (!res) { - throw new MtTypeAssertionError( - 'help.acceptTermsOfService', - 'true', - 'false', - ) + throw new MtTypeAssertionError('help.acceptTermsOfService', 'true', 'false') } return true diff --git a/packages/client/src/methods/auth/check-password.ts b/packages/client/src/methods/auth/check-password.ts index 813c0760..5bb6d311 100644 --- a/packages/client/src/methods/auth/check-password.ts +++ b/packages/client/src/methods/auth/check-password.ts @@ -11,10 +11,7 @@ import { User } from '../../types' * @throws BadRequestError In case the password is invalid * @internal */ -export async function checkPassword( - this: TelegramClient, - password: string, -): Promise { +export async function checkPassword(this: TelegramClient, password: string): Promise { const res = await this.call({ _: 'auth.checkPassword', password: await computeSrpParams( @@ -26,16 +23,8 @@ export async function checkPassword( ), }) - assertTypeIs( - 'checkPassword (@ auth.checkPassword)', - res, - 'auth.authorization', - ) - assertTypeIs( - 'checkPassword (@ auth.checkPassword -> user)', - res.user, - 'user', - ) + assertTypeIs('checkPassword (@ auth.checkPassword)', res, 'auth.authorization') + assertTypeIs('checkPassword (@ auth.checkPassword -> user)', res.user, 'user') this._userId = res.user.id this.log.prefix = `[USER ${this._userId}] ` diff --git a/packages/client/src/methods/auth/recover-password.ts b/packages/client/src/methods/auth/recover-password.ts index 631126a2..91ddd36d 100644 --- a/packages/client/src/methods/auth/recover-password.ts +++ b/packages/client/src/methods/auth/recover-password.ts @@ -11,25 +11,14 @@ import { User } from '../../types' * @throws BadRequestError In case the code is invalid * @internal */ -export async function recoverPassword( - this: TelegramClient, - recoveryCode: string, -): Promise { +export async function recoverPassword(this: TelegramClient, recoveryCode: string): Promise { const res = await this.call({ _: 'auth.recoverPassword', code: recoveryCode, }) - assertTypeIs( - 'recoverPassword (@ auth.recoverPassword)', - res, - 'auth.authorization', - ) - assertTypeIs( - 'recoverPassword (@ auth.recoverPassword -> user)', - res.user, - 'user', - ) + assertTypeIs('recoverPassword (@ auth.recoverPassword)', res, 'auth.authorization') + assertTypeIs('recoverPassword (@ auth.recoverPassword -> user)', res.user, 'user') this._userId = res.user.id this._isBot = false diff --git a/packages/client/src/methods/auth/resend-code.ts b/packages/client/src/methods/auth/resend-code.ts index 05c17f11..bb7a0411 100644 --- a/packages/client/src/methods/auth/resend-code.ts +++ b/packages/client/src/methods/auth/resend-code.ts @@ -14,11 +14,7 @@ import { normalizePhoneNumber } from '../../utils/misc-utils' * @param phoneCodeHash Confirmation code identifier from {@link SentCode} * @internal */ -export async function resendCode( - this: TelegramClient, - phone: string, - phoneCodeHash: string, -): Promise { +export async function resendCode(this: TelegramClient, phone: string, phoneCodeHash: string): Promise { phone = normalizePhoneNumber(phone) const res = await this.call({ diff --git a/packages/client/src/methods/auth/send-code.ts b/packages/client/src/methods/auth/send-code.ts index 772b30ac..9d46b57c 100644 --- a/packages/client/src/methods/auth/send-code.ts +++ b/packages/client/src/methods/auth/send-code.ts @@ -11,10 +11,7 @@ import { normalizePhoneNumber } from '../../utils/misc-utils' * @returns An object containing information about the sent confirmation code * @internal */ -export async function sendCode( - this: TelegramClient, - phone: string, -): Promise { +export async function sendCode(this: TelegramClient, phone: string): Promise { phone = normalizePhoneNumber(phone) const res = await this.call({ diff --git a/packages/client/src/methods/auth/sign-in-bot.ts b/packages/client/src/methods/auth/sign-in-bot.ts index 02289366..0190d5a0 100644 --- a/packages/client/src/methods/auth/sign-in-bot.ts +++ b/packages/client/src/methods/auth/sign-in-bot.ts @@ -11,10 +11,7 @@ import { User } from '../../types' * @throws BadRequestError In case the bot token is invalid * @internal */ -export async function signInBot( - this: TelegramClient, - token: string, -): Promise { +export async function signInBot(this: TelegramClient, token: string): Promise { const res = await this.call({ _: 'auth.importBotAuthorization', flags: 0, @@ -23,16 +20,8 @@ export async function signInBot( botAuthToken: token, }) - assertTypeIs( - 'signInBot (@ auth.importBotAuthorization)', - res, - 'auth.authorization', - ) - assertTypeIs( - 'signInBot (@ auth.importBotAuthorization -> user)', - res.user, - 'user', - ) + assertTypeIs('signInBot (@ auth.importBotAuthorization)', res, 'auth.authorization') + assertTypeIs('signInBot (@ auth.importBotAuthorization -> user)', res.user, 'user') this._userId = res.user.id this.log.prefix = `[USER ${this._userId}] ` diff --git a/packages/client/src/methods/auth/start-test.ts b/packages/client/src/methods/auth/start-test.ts index 37248ccf..4d12ea40 100644 --- a/packages/client/src/methods/auth/start-test.ts +++ b/packages/client/src/methods/auth/start-test.ts @@ -72,9 +72,7 @@ export async function startTest( if (phone) { if (!phone.match(/^99966\d{5}/)) { - throw new MtArgumentError( - `${phone} is an invalid test phone number`, - ) + throw new MtArgumentError(`${phone} is an invalid test phone number`) } const id = parseInt(phone[5]) diff --git a/packages/client/src/methods/auth/start.ts b/packages/client/src/methods/auth/start.ts index d1370284..184c6c84 100644 --- a/packages/client/src/methods/auth/start.ts +++ b/packages/client/src/methods/auth/start.ts @@ -3,17 +3,8 @@ import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - MaybeAsync, - MaybeDynamic, - SentCode, - TermsOfService, - User, -} from '../../types' -import { - normalizePhoneNumber, - resolveMaybeDynamic, -} from '../../utils/misc-utils' +import { MaybeAsync, MaybeDynamic, SentCode, TermsOfService, User } from '../../types' +import { normalizePhoneNumber, resolveMaybeDynamic } from '../../utils/misc-utils' /** * Start the client in an interactive and declarative manner, @@ -148,13 +139,7 @@ export async function start( // user is already authorized this.log.prefix = `[USER ${me.id}] ` - this.log.info( - 'Logged in as %s (ID: %s, username: %s, bot: %s)', - me.displayName, - me.id, - me.username, - me.isBot, - ) + this.log.info('Logged in as %s (ID: %s, username: %s, bot: %s)', me.displayName, me.id, me.username, me.isBot) this.network.setIsPremium(me.isPremium) @@ -191,14 +176,10 @@ export async function start( throw new MtArgumentError('You must pass `code` to use `phone`') } } else { - const botToken = params.botToken ? - await resolveMaybeDynamic(params.botToken) : - null + const botToken = params.botToken ? await resolveMaybeDynamic(params.botToken) : null if (!botToken) { - throw new MtArgumentError( - 'Either bot token or phone number must be provided', - ) + throw new MtArgumentError('Either bot token or phone number must be provided') } return await this.signInBot(botToken) @@ -258,9 +239,7 @@ export async function start( if (has2fa) { if (!params.password) { - throw new MtArgumentError( - '2FA is enabled, but `password` was not provided.', - ) + throw new MtArgumentError('2FA is enabled, but `password` was not provided.') } for (;;) { diff --git a/packages/client/src/methods/bots/answer-inline-query.ts b/packages/client/src/methods/bots/answer-inline-query.ts index 2d50ac84..ae650eb0 100644 --- a/packages/client/src/methods/bots/answer-inline-query.ts +++ b/packages/client/src/methods/bots/answer-inline-query.ts @@ -97,11 +97,7 @@ export async function answerInlineQuery( ): Promise { if (!params) params = {} - const [gallery, tlResults] = await BotInline._convertToTl( - this, - results, - params.parseMode, - ) + const [gallery, tlResults] = await BotInline._convertToTl(this, results, params.parseMode) await this.call({ _: 'messages.setInlineBotResults', diff --git a/packages/client/src/methods/bots/answer-pre-checkout-query.ts b/packages/client/src/methods/bots/answer-pre-checkout-query.ts index f470fb54..8010c55a 100644 --- a/packages/client/src/methods/bots/answer-pre-checkout-query.ts +++ b/packages/client/src/methods/bots/answer-pre-checkout-query.ts @@ -9,11 +9,7 @@ import { TelegramClient } from '../../client' * @param error If pre-checkout is rejected, error message to show to the user * @internal */ -export async function answerPreCheckoutQuery( - this: TelegramClient, - queryId: tl.Long, - error?: string, -): Promise { +export async function answerPreCheckoutQuery(this: TelegramClient, queryId: tl.Long, error?: string): Promise { await this.call({ _: 'messages.setBotPrecheckoutResults', queryId, diff --git a/packages/client/src/methods/bots/get-bot-menu-button.ts b/packages/client/src/methods/bots/get-bot-menu-button.ts index 92f4c7ee..f008e1e2 100644 --- a/packages/client/src/methods/bots/get-bot-menu-button.ts +++ b/packages/client/src/methods/bots/get-bot-menu-button.ts @@ -9,10 +9,7 @@ import { normalizeToInputUser } from '../../utils/peer-utils' * * @internal */ -export async function getBotMenuButton( - this: TelegramClient, - user: InputPeerLike, -): Promise { +export async function getBotMenuButton(this: TelegramClient, user: InputPeerLike): Promise { return await this.call({ _: 'bots.getBotMenuButton', userId: normalizeToInputUser(await this.resolvePeer(user), user), diff --git a/packages/client/src/methods/bots/normalize-command-scope.ts b/packages/client/src/methods/bots/normalize-command-scope.ts index 2e3bc50b..b4d583d1 100644 --- a/packages/client/src/methods/bots/normalize-command-scope.ts +++ b/packages/client/src/methods/bots/normalize-command-scope.ts @@ -18,18 +18,12 @@ export async function _normalizeCommandScope( const peer = await this.resolvePeer(scope.peer) return { - _: - scope.type === 'peer' ? - 'botCommandScopePeer' : - 'botCommandScopePeerAdmins', + _: scope.type === 'peer' ? 'botCommandScopePeer' : 'botCommandScopePeerAdmins', peer, } } case 'member': { - const user = normalizeToInputUser( - await this.resolvePeer(scope.user), - scope.user, - ) + const user = normalizeToInputUser(await this.resolvePeer(scope.user), scope.user) const chat = await this.resolvePeer(scope.chat) return { diff --git a/packages/client/src/methods/bots/set-my-default-rights.ts b/packages/client/src/methods/bots/set-my-default-rights.ts index 8957685f..017cbb1d 100644 --- a/packages/client/src/methods/bots/set-my-default-rights.ts +++ b/packages/client/src/methods/bots/set-my-default-rights.ts @@ -15,10 +15,7 @@ export async function setMyDefaultRights( rights: Omit, ): Promise { await this.call({ - _: - target === 'group' ? - 'bots.setBotGroupDefaultAdminRights' : - 'bots.setBotBroadcastDefaultAdminRights', + _: target === 'group' ? 'bots.setBotGroupDefaultAdminRights' : 'bots.setBotBroadcastDefaultAdminRights', adminRights: { _: 'chatAdminRights', ...rights, diff --git a/packages/client/src/methods/chats/archive-chats.ts b/packages/client/src/methods/chats/archive-chats.ts index 37ddcf6f..0de723d5 100644 --- a/packages/client/src/methods/chats/archive-chats.ts +++ b/packages/client/src/methods/chats/archive-chats.ts @@ -10,10 +10,7 @@ import { InputPeerLike } from '../../types' * @param chats Chat ID(s), username(s), phone number(s), `"me"` or `"self"` * @internal */ -export async function archiveChats( - this: TelegramClient, - chats: MaybeArray, -): Promise { +export async function archiveChats(this: TelegramClient, chats: MaybeArray): Promise { if (!Array.isArray(chats)) chats = [chats] const folderPeers: tl.TypeInputFolderPeer[] = [] diff --git a/packages/client/src/methods/chats/ban-chat-member.ts b/packages/client/src/methods/chats/ban-chat-member.ts index 0a005c37..b68c3529 100644 --- a/packages/client/src/methods/chats/ban-chat-member.ts +++ b/packages/client/src/methods/chats/ban-chat-member.ts @@ -51,10 +51,7 @@ export async function banChatMember( try { return this._findMessageInUpdate(res) } catch (e) { - if ( - e instanceof MtTypeAssertionError && - e.context === '_findInUpdate (@ .updates[*])' - ) { + if (e instanceof MtTypeAssertionError && e.context === '_findInUpdate (@ .updates[*])') { // no service message return null } diff --git a/packages/client/src/methods/chats/create-channel.ts b/packages/client/src/methods/chats/create-channel.ts index 0900c7f8..d06b8349 100644 --- a/packages/client/src/methods/chats/create-channel.ts +++ b/packages/client/src/methods/chats/create-channel.ts @@ -10,11 +10,7 @@ import { assertIsUpdatesGroup } from '../../utils/updates-utils' * @returns Newly created channel * @internal */ -export async function createChannel( - this: TelegramClient, - title: string, - description = '', -): Promise { +export async function createChannel(this: TelegramClient, title: string, description = ''): Promise { const res = await this.call({ _: 'channels.createChannel', title, diff --git a/packages/client/src/methods/chats/create-supergroup.ts b/packages/client/src/methods/chats/create-supergroup.ts index 1c130c4e..fc61aaa7 100644 --- a/packages/client/src/methods/chats/create-supergroup.ts +++ b/packages/client/src/methods/chats/create-supergroup.ts @@ -9,11 +9,7 @@ import { assertIsUpdatesGroup } from '../../utils/updates-utils' * @param description Description of the supergroup * @internal */ -export async function createSupergroup( - this: TelegramClient, - title: string, - description = '', -): Promise { +export async function createSupergroup(this: TelegramClient, title: string, description = ''): Promise { const res = await this.call({ _: 'channels.createChannel', title, diff --git a/packages/client/src/methods/chats/delete-channel.ts b/packages/client/src/methods/chats/delete-channel.ts index b850fed5..d7f18ec1 100644 --- a/packages/client/src/methods/chats/delete-channel.ts +++ b/packages/client/src/methods/chats/delete-channel.ts @@ -9,16 +9,10 @@ import { normalizeToInputChannel } from '../../utils/peer-utils' * @param chatId Chat ID or username * @internal */ -export async function deleteChannel( - this: TelegramClient, - chatId: InputPeerLike, -): Promise { +export async function deleteChannel(this: TelegramClient, chatId: InputPeerLike): Promise { const res = await this.call({ _: 'channels.deleteChannel', - channel: normalizeToInputChannel( - await this.resolvePeer(chatId), - chatId, - ), + channel: normalizeToInputChannel(await this.resolvePeer(chatId), chatId), }) this._handleUpdate(res) } diff --git a/packages/client/src/methods/chats/delete-chat-photo.ts b/packages/client/src/methods/chats/delete-chat-photo.ts index 510b127d..dc2ad751 100644 --- a/packages/client/src/methods/chats/delete-chat-photo.ts +++ b/packages/client/src/methods/chats/delete-chat-photo.ts @@ -1,10 +1,6 @@ import { TelegramClient } from '../../client' import { InputPeerLike, MtInvalidPeerTypeError } from '../../types' -import { - isInputPeerChannel, - isInputPeerChat, - normalizeToInputChannel, -} from '../../utils/peer-utils' +import { isInputPeerChannel, isInputPeerChat, normalizeToInputChannel } from '../../utils/peer-utils' /** * Delete a chat photo @@ -14,10 +10,7 @@ import { * @param chatId Chat ID or username * @internal */ -export async function deleteChatPhoto( - this: TelegramClient, - chatId: InputPeerLike, -): Promise { +export async function deleteChatPhoto(this: TelegramClient, chatId: InputPeerLike): Promise { const chat = await this.resolvePeer(chatId) let res diff --git a/packages/client/src/methods/chats/delete-group.ts b/packages/client/src/methods/chats/delete-group.ts index e2e4803b..249ab2a2 100644 --- a/packages/client/src/methods/chats/delete-group.ts +++ b/packages/client/src/methods/chats/delete-group.ts @@ -8,10 +8,7 @@ import { isInputPeerChat } from '../../utils/peer-utils' * @param chatId Chat ID * @internal */ -export async function deleteGroup( - this: TelegramClient, - chatId: InputPeerLike, -): Promise { +export async function deleteGroup(this: TelegramClient, chatId: InputPeerLike): Promise { const chat = await this.resolvePeer(chatId) if (!isInputPeerChat(chat)) throw new MtInvalidPeerTypeError(chatId, 'chat') diff --git a/packages/client/src/methods/chats/delete-history.ts b/packages/client/src/methods/chats/delete-history.ts index 1993f22a..4591afe9 100644 --- a/packages/client/src/methods/chats/delete-history.ts +++ b/packages/client/src/methods/chats/delete-history.ts @@ -35,9 +35,7 @@ export async function deleteHistory( }) if (isInputPeerChannel(peer)) { - this._handleUpdate( - createDummyUpdate(res.pts, res.ptsCount, peer.channelId), - ) + this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount, peer.channelId)) } else { this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount)) } diff --git a/packages/client/src/methods/chats/delete-user-history.ts b/packages/client/src/methods/chats/delete-user-history.ts index f887dc6a..e2c9de7e 100644 --- a/packages/client/src/methods/chats/delete-user-history.ts +++ b/packages/client/src/methods/chats/delete-user-history.ts @@ -17,10 +17,7 @@ export async function deleteUserHistory( chatId: InputPeerLike, participantId: InputPeerLike, ): Promise { - const channel = normalizeToInputChannel( - await this.resolvePeer(chatId), - chatId, - ) + const channel = normalizeToInputChannel(await this.resolvePeer(chatId), chatId) const peer = await this.resolvePeer(participantId) @@ -30,11 +27,5 @@ export async function deleteUserHistory( participant: peer, }) - this._handleUpdate( - createDummyUpdate( - res.pts, - res.ptsCount, - (channel as tl.RawInputChannel).channelId, - ), - ) + this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount, (channel as tl.RawInputChannel).channelId)) } diff --git a/packages/client/src/methods/chats/edit-admin-rights.ts b/packages/client/src/methods/chats/edit-admin-rights.ts index 42d80791..2201cc4a 100644 --- a/packages/client/src/methods/chats/edit-admin-rights.ts +++ b/packages/client/src/methods/chats/edit-admin-rights.ts @@ -2,10 +2,7 @@ import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { InputPeerLike } from '../../types' -import { - normalizeToInputChannel, - normalizeToInputUser, -} from '../../utils/peer-utils' +import { normalizeToInputChannel, normalizeToInputUser } from '../../utils/peer-utils' /** * Edit supergroup/channel admin rights of a user. diff --git a/packages/client/src/methods/chats/get-chat-event-log.ts b/packages/client/src/methods/chats/get-chat-event-log.ts index 528e7e7a..37bb0644 100644 --- a/packages/client/src/methods/chats/get-chat-event-log.ts +++ b/packages/client/src/methods/chats/get-chat-event-log.ts @@ -4,16 +4,8 @@ import { assertNever, MaybeArray } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - ChatAction, - ChatEvent, - InputPeerLike, - PeersIndex, -} from '../../types' -import { - normalizeToInputChannel, - normalizeToInputUser, -} from '../../utils/peer-utils' +import { ChatAction, ChatEvent, InputPeerLike, PeersIndex } from '../../types' +import { normalizeToInputChannel, normalizeToInputUser } from '../../utils/peer-utils' /** * Get chat event log ("Recent actions" in official @@ -66,9 +58,7 @@ export async function* getChatEventLog( * and when passing one or more action types, * they will be filtered locally. */ - filters?: - | tl.TypeChannelAdminLogEventsFilter - | MaybeArray['type']> + filters?: tl.TypeChannelAdminLogEventsFilter | MaybeArray['type']> /** * Limit the number of events returned. @@ -101,16 +91,11 @@ export async function* getChatEventLog( await this.resolvePeerMany(params.users, normalizeToInputUser) : undefined - let serverFilter: - | tl.Mutable - | undefined = undefined + let serverFilter: tl.Mutable | undefined = undefined let localFilter: Record | undefined = undefined if (params.filters) { - if ( - typeof params.filters === 'string' || - Array.isArray(params.filters) - ) { + if (typeof params.filters === 'string' || Array.isArray(params.filters)) { let input = params.filters if (!Array.isArray(input)) input = [input] @@ -224,10 +209,9 @@ export async function* getChatEventLog( for (const evt of res.events) { const parsed = new ChatEvent(this, evt, peers) - if ( - localFilter && - (!parsed.action || !localFilter[parsed.action.type]) - ) { continue } + if (localFilter && (!parsed.action || !localFilter[parsed.action.type])) { + continue + } current += 1 yield parsed diff --git a/packages/client/src/methods/chats/get-chat-member.ts b/packages/client/src/methods/chats/get-chat-member.ts index 62680e85..2d20a8c1 100644 --- a/packages/client/src/methods/chats/get-chat-member.ts +++ b/packages/client/src/methods/chats/get-chat-member.ts @@ -2,18 +2,8 @@ import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - ChatMember, - InputPeerLike, - MtInvalidPeerTypeError, - PeersIndex, -} from '../../types' -import { - isInputPeerChannel, - isInputPeerChat, - isInputPeerUser, - normalizeToInputChannel, -} from '../../utils/peer-utils' +import { ChatMember, InputPeerLike, MtInvalidPeerTypeError, PeersIndex } from '../../types' +import { isInputPeerChannel, isInputPeerChat, isInputPeerUser, normalizeToInputChannel } from '../../utils/peer-utils' /** * Get information about a single chat member @@ -41,23 +31,16 @@ export async function getChatMember( chatId: chat.chatId, }) - assertTypeIs( - 'getChatMember (@ messages.getFullChat)', - res.fullChat, - 'chatFull', - ) + assertTypeIs('getChatMember (@ messages.getFullChat)', res.fullChat, 'chatFull') const members = - res.fullChat.participants._ === 'chatParticipantsForbidden' ? - [] : - res.fullChat.participants.participants + res.fullChat.participants._ === 'chatParticipantsForbidden' ? [] : res.fullChat.participants.participants const peers = PeersIndex.from(res) for (const m of members) { if ( - (user._ === 'inputPeerSelf' && - (peers.user(m.userId) as tl.RawUser).self) || + (user._ === 'inputPeerSelf' && (peers.user(m.userId) as tl.RawUser).self) || (user._ === 'inputPeerUser' && m.userId === user.userId) ) { return new ChatMember(this, m, peers) diff --git a/packages/client/src/methods/chats/get-chat-members.ts b/packages/client/src/methods/chats/get-chat-members.ts index 1d4180ac..b008cf35 100644 --- a/packages/client/src/methods/chats/get-chat-members.ts +++ b/packages/client/src/methods/chats/get-chat-members.ts @@ -5,18 +5,8 @@ import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - ArrayWithTotal, - ChatMember, - InputPeerLike, - MtInvalidPeerTypeError, - PeersIndex, -} from '../../types' -import { - isInputPeerChannel, - isInputPeerChat, - normalizeToInputChannel, -} from '../../utils/peer-utils' +import { ArrayWithTotal, ChatMember, InputPeerLike, MtInvalidPeerTypeError, PeersIndex } from '../../types' +import { isInputPeerChannel, isInputPeerChat, normalizeToInputChannel } from '../../utils/peer-utils' /** * Get a chunk of members of some chat. @@ -63,15 +53,7 @@ export async function getChatMembers( * * Only used for channels and supergroups. Defaults to `recent` */ - type?: - | 'all' - | 'banned' - | 'restricted' - | 'bots' - | 'recent' - | 'admins' - | 'contacts' - | 'mention' + type?: 'all' | 'banned' | 'restricted' | 'bots' | 'recent' | 'admins' | 'contacts' | 'mention' }, ): Promise> { if (!params) params = {} @@ -84,25 +66,17 @@ export async function getChatMembers( chatId: chat.chatId, }) - assertTypeIs( - 'getChatMember (@ messages.getFullChat)', - res.fullChat, - 'chatFull', - ) + assertTypeIs('getChatMember (@ messages.getFullChat)', res.fullChat, 'chatFull') let members = - res.fullChat.participants._ === 'chatParticipantsForbidden' ? - [] : - res.fullChat.participants.participants + res.fullChat.participants._ === 'chatParticipantsForbidden' ? [] : res.fullChat.participants.participants if (params.offset) members = members.slice(params.offset) if (params.limit) members = members.slice(0, params.limit) const peers = PeersIndex.from(res) - const ret = members.map( - (m) => new ChatMember(this, m, peers), - ) as ArrayWithTotal + const ret = members.map((m) => new ChatMember(this, m, peers)) as ArrayWithTotal ret.total = ret.length @@ -153,17 +127,11 @@ export async function getChatMembers( hash: Long.ZERO, }) - assertTypeIs( - 'getChatMembers (@ channels.getParticipants)', - res, - 'channels.channelParticipants', - ) + assertTypeIs('getChatMembers (@ channels.getParticipants)', res, 'channels.channelParticipants') const peers = PeersIndex.from(res) - const ret = res.participants.map( - (i) => new ChatMember(this, i, peers), - ) as ArrayWithTotal + const ret = res.participants.map((i) => new ChatMember(this, i, peers)) as ArrayWithTotal ret.total = res.count return ret diff --git a/packages/client/src/methods/chats/get-chat-preview.ts b/packages/client/src/methods/chats/get-chat-preview.ts index 52a9cdfc..fe3a6597 100644 --- a/packages/client/src/methods/chats/get-chat-preview.ts +++ b/packages/client/src/methods/chats/get-chat-preview.ts @@ -14,10 +14,7 @@ import { INVITE_LINK_REGEX } from '../../utils/peer-utils' * Use {@link getChat} or {@link getFullChat} instead. * @internal */ -export async function getChatPreview( - this: TelegramClient, - inviteLink: string, -): Promise { +export async function getChatPreview(this: TelegramClient, inviteLink: string): Promise { const m = inviteLink.match(INVITE_LINK_REGEX) if (!m) throw new MtArgumentError('Invalid invite link') diff --git a/packages/client/src/methods/chats/get-chat.ts b/packages/client/src/methods/chats/get-chat.ts index 7b9896aa..7b9cf98e 100644 --- a/packages/client/src/methods/chats/get-chat.ts +++ b/packages/client/src/methods/chats/get-chat.ts @@ -21,10 +21,7 @@ import { * Use {@link getChatPreview} instead. * @internal */ -export async function getChat( - this: TelegramClient, - chatId: InputPeerLike, -): Promise { +export async function getChat(this: TelegramClient, chatId: InputPeerLike): Promise { if (typeof chatId === 'string') { const m = chatId.match(INVITE_LINK_REGEX) @@ -35,9 +32,7 @@ export async function getChat( }) if (res._ === 'chatInvite') { - throw new MtArgumentError( - `You haven't joined ${JSON.stringify(res.title)}`, - ) + throw new MtArgumentError(`You haven't joined ${JSON.stringify(res.title)}`) } return new Chat(this, res.chat) diff --git a/packages/client/src/methods/chats/get-full-chat.ts b/packages/client/src/methods/chats/get-full-chat.ts index 57394bea..7cba82cc 100644 --- a/packages/client/src/methods/chats/get-full-chat.ts +++ b/packages/client/src/methods/chats/get-full-chat.ts @@ -21,10 +21,7 @@ import { * Use {@link getChatPreview} instead. * @internal */ -export async function getFullChat( - this: TelegramClient, - chatId: InputPeerLike, -): Promise { +export async function getFullChat(this: TelegramClient, chatId: InputPeerLike): Promise { if (typeof chatId === 'string') { const m = chatId.match(INVITE_LINK_REGEX) @@ -35,9 +32,7 @@ export async function getFullChat( }) if (res._ === 'chatInvite') { - throw new MtArgumentError( - `You haven't joined ${JSON.stringify(res.title)}`, - ) + throw new MtArgumentError(`You haven't joined ${JSON.stringify(res.title)}`) } // we still need to fetch full chat info diff --git a/packages/client/src/methods/chats/get-nearby-chats.ts b/packages/client/src/methods/chats/get-nearby-chats.ts index 99ba9538..7c900844 100644 --- a/packages/client/src/methods/chats/get-nearby-chats.ts +++ b/packages/client/src/methods/chats/get-nearby-chats.ts @@ -13,11 +13,7 @@ import { assertIsUpdatesGroup } from '../../utils/updates-utils' * @param longitude Longitude of the location * @internal */ -export async function getNearbyChats( - this: TelegramClient, - latitude: number, - longitude: number, -): Promise { +export async function getNearbyChats(this: TelegramClient, latitude: number, longitude: number): Promise { const res = await this.call({ _: 'contacts.getLocated', geoPoint: { @@ -32,11 +28,7 @@ export async function getNearbyChats( if (!res.updates.length) return [] - assertTypeIs( - 'contacts.getLocated (@ .updates[0])', - res.updates[0], - 'updatePeerLocated', - ) + assertTypeIs('contacts.getLocated (@ .updates[0])', res.updates[0], 'updatePeerLocated') const chats = res.chats.map((it) => new Chat(this, it)) diff --git a/packages/client/src/methods/chats/join-chat.ts b/packages/client/src/methods/chats/join-chat.ts index 3a438521..dc71c89d 100644 --- a/packages/client/src/methods/chats/join-chat.ts +++ b/packages/client/src/methods/chats/join-chat.ts @@ -1,9 +1,6 @@ import { TelegramClient } from '../../client' import { Chat, InputPeerLike } from '../../types' -import { - INVITE_LINK_REGEX, - normalizeToInputChannel, -} from '../../utils/peer-utils' +import { INVITE_LINK_REGEX, normalizeToInputChannel } from '../../utils/peer-utils' import { assertIsUpdatesGroup } from '../../utils/updates-utils' /** @@ -18,10 +15,7 @@ import { assertIsUpdatesGroup } from '../../utils/updates-utils' * or ID of the linked supergroup or channel. * @internal */ -export async function joinChat( - this: TelegramClient, - chatId: InputPeerLike, -): Promise { +export async function joinChat(this: TelegramClient, chatId: InputPeerLike): Promise { if (typeof chatId === 'string') { const m = chatId.match(INVITE_LINK_REGEX) @@ -40,10 +34,7 @@ export async function joinChat( const res = await this.call({ _: 'channels.joinChannel', - channel: normalizeToInputChannel( - await this.resolvePeer(chatId), - chatId, - ), + channel: normalizeToInputChannel(await this.resolvePeer(chatId), chatId), }) assertIsUpdatesGroup('channels.joinChannel', res) diff --git a/packages/client/src/methods/chats/leave-chat.ts b/packages/client/src/methods/chats/leave-chat.ts index c0e7dd29..8c60373b 100644 --- a/packages/client/src/methods/chats/leave-chat.ts +++ b/packages/client/src/methods/chats/leave-chat.ts @@ -1,10 +1,6 @@ import { TelegramClient } from '../../client' import { InputPeerLike, MtInvalidPeerTypeError } from '../../types' -import { - isInputPeerChannel, - isInputPeerChat, - normalizeToInputChannel, -} from '../../utils/peer-utils' +import { isInputPeerChannel, isInputPeerChat, normalizeToInputChannel } from '../../utils/peer-utils' /** * Leave a group chat, supergroup or channel @@ -13,11 +9,7 @@ import { * @param clear Whether to clear history after leaving (only for legacy group chats) * @internal */ -export async function leaveChat( - this: TelegramClient, - chatId: InputPeerLike, - clear = false, -): Promise { +export async function leaveChat(this: TelegramClient, chatId: InputPeerLike, clear = false): Promise { const chat = await this.resolvePeer(chatId) if (isInputPeerChannel(chat)) { diff --git a/packages/client/src/methods/chats/mark-chat-unread.ts b/packages/client/src/methods/chats/mark-chat-unread.ts index 3bea5f56..ed7f971e 100644 --- a/packages/client/src/methods/chats/mark-chat-unread.ts +++ b/packages/client/src/methods/chats/mark-chat-unread.ts @@ -7,10 +7,7 @@ import { InputPeerLike } from '../../types' * @param chatId Chat ID * @internal */ -export async function markChatUnread( - this: TelegramClient, - chatId: InputPeerLike, -): Promise { +export async function markChatUnread(this: TelegramClient, chatId: InputPeerLike): Promise { await this.call({ _: 'messages.markDialogUnread', peer: { diff --git a/packages/client/src/methods/chats/restrict-chat-member.ts b/packages/client/src/methods/chats/restrict-chat-member.ts index bfe2d611..0e8d88ec 100644 --- a/packages/client/src/methods/chats/restrict-chat-member.ts +++ b/packages/client/src/methods/chats/restrict-chat-member.ts @@ -3,10 +3,7 @@ import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { InputPeerLike, MtInvalidPeerTypeError } from '../../types' import { normalizeDate } from '../../utils/misc-utils' -import { - isInputPeerChannel, - normalizeToInputChannel, -} from '../../utils/peer-utils' +import { isInputPeerChannel, normalizeToInputChannel } from '../../utils/peer-utils' /** * Restrict a user in a supergroup. @@ -34,7 +31,9 @@ export async function restrictChatMember( ): Promise { const chat = await this.resolvePeer(chatId) - if (!isInputPeerChannel(chat)) { throw new MtInvalidPeerTypeError(chatId, 'channel') } + if (!isInputPeerChannel(chat)) { + throw new MtInvalidPeerTypeError(chatId, 'channel') + } const user = await this.resolvePeer(userId) diff --git a/packages/client/src/methods/chats/set-chat-photo.ts b/packages/client/src/methods/chats/set-chat-photo.ts index e9122aab..2f901439 100644 --- a/packages/client/src/methods/chats/set-chat-photo.ts +++ b/packages/client/src/methods/chats/set-chat-photo.ts @@ -3,17 +3,8 @@ import { fileIdToInputPhoto, tdFileId } from '@mtcute/file-id' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - InputFileLike, - InputPeerLike, - isUploadedFile, - MtInvalidPeerTypeError, -} from '../../types' -import { - isInputPeerChannel, - isInputPeerChat, - normalizeToInputChannel, -} from '../../utils/peer-utils' +import { InputFileLike, InputPeerLike, isUploadedFile, MtInvalidPeerTypeError } from '../../types' +import { isInputPeerChannel, isInputPeerChat, normalizeToInputChannel } from '../../utils/peer-utils' /** * Set a new chat photo or video. diff --git a/packages/client/src/methods/chats/set-chat-title.ts b/packages/client/src/methods/chats/set-chat-title.ts index be5b65a5..08c52b98 100644 --- a/packages/client/src/methods/chats/set-chat-title.ts +++ b/packages/client/src/methods/chats/set-chat-title.ts @@ -1,10 +1,6 @@ import { TelegramClient } from '../../client' import { InputPeerLike, MtInvalidPeerTypeError } from '../../types' -import { - isInputPeerChannel, - isInputPeerChat, - normalizeToInputChannel, -} from '../../utils/peer-utils' +import { isInputPeerChannel, isInputPeerChat, normalizeToInputChannel } from '../../utils/peer-utils' /** * Change chat title @@ -15,11 +11,7 @@ import { * @param title New chat title, 1-255 characters * @internal */ -export async function setChatTitle( - this: TelegramClient, - chatId: InputPeerLike, - title: string, -): Promise { +export async function setChatTitle(this: TelegramClient, chatId: InputPeerLike, title: string): Promise { const chat = await this.resolvePeer(chatId) let res diff --git a/packages/client/src/methods/chats/set-chat-username.ts b/packages/client/src/methods/chats/set-chat-username.ts index a18d7864..d7c82439 100644 --- a/packages/client/src/methods/chats/set-chat-username.ts +++ b/packages/client/src/methods/chats/set-chat-username.ts @@ -18,10 +18,7 @@ export async function setChatUsername( ): Promise { await this.call({ _: 'channels.updateUsername', - channel: normalizeToInputChannel( - await this.resolvePeer(chatId), - chatId, - ), + channel: normalizeToInputChannel(await this.resolvePeer(chatId), chatId), username: username || '', }) } diff --git a/packages/client/src/methods/chats/set-slow-mode.ts b/packages/client/src/methods/chats/set-slow-mode.ts index 62cf7d27..ff91a685 100644 --- a/packages/client/src/methods/chats/set-slow-mode.ts +++ b/packages/client/src/methods/chats/set-slow-mode.ts @@ -12,17 +12,10 @@ import { normalizeToInputChannel } from '../../utils/peer-utils' * Valid values are: `0 (off), 10, 30, 60 (1m), 300 (5m), 900 (15m) or 3600 (1h)` * @internal */ -export async function setSlowMode( - this: TelegramClient, - chatId: InputPeerLike, - seconds = 0, -): Promise { +export async function setSlowMode(this: TelegramClient, chatId: InputPeerLike, seconds = 0): Promise { const res = await this.call({ _: 'channels.toggleSlowMode', - channel: normalizeToInputChannel( - await this.resolvePeer(chatId), - chatId, - ), + channel: normalizeToInputChannel(await this.resolvePeer(chatId), chatId), seconds, }) this._handleUpdate(res) diff --git a/packages/client/src/methods/chats/unarchive-chats.ts b/packages/client/src/methods/chats/unarchive-chats.ts index b5c0b55b..f98cc66c 100644 --- a/packages/client/src/methods/chats/unarchive-chats.ts +++ b/packages/client/src/methods/chats/unarchive-chats.ts @@ -10,10 +10,7 @@ import { InputPeerLike } from '../../types' * @param chats Chat ID(s), username(s), phone number(s), `"me"` or `"self"` * @internal */ -export async function unarchiveChats( - this: TelegramClient, - chats: MaybeArray, -): Promise { +export async function unarchiveChats(this: TelegramClient, chats: MaybeArray): Promise { if (!Array.isArray(chats)) chats = [chats] const folderPeers: tl.TypeInputFolderPeer[] = [] diff --git a/packages/client/src/methods/chats/unban-chat-member.ts b/packages/client/src/methods/chats/unban-chat-member.ts index efe8ea86..44dc44c6 100644 --- a/packages/client/src/methods/chats/unban-chat-member.ts +++ b/packages/client/src/methods/chats/unban-chat-member.ts @@ -1,10 +1,6 @@ import { TelegramClient } from '../../client' import { InputPeerLike, MtInvalidPeerTypeError } from '../../types' -import { - isInputPeerChannel, - isInputPeerChat, - normalizeToInputChannel, -} from '../../utils/peer-utils' +import { isInputPeerChannel, isInputPeerChat, normalizeToInputChannel } from '../../utils/peer-utils' // @alias=unrestrictChatMember /** diff --git a/packages/client/src/methods/contacts/delete-contacts.ts b/packages/client/src/methods/contacts/delete-contacts.ts index 050a0869..f1332879 100644 --- a/packages/client/src/methods/contacts/delete-contacts.ts +++ b/packages/client/src/methods/contacts/delete-contacts.ts @@ -14,10 +14,7 @@ import { assertIsUpdatesGroup } from '../../utils/updates-utils' * @param userId User ID, username or phone number * @internal */ -export async function deleteContacts( - this: TelegramClient, - userId: InputPeerLike -): Promise +export async function deleteContacts(this: TelegramClient, userId: InputPeerLike): Promise /** * Delete one or more contacts from your Telegram contacts list @@ -28,10 +25,7 @@ export async function deleteContacts( * @param userIds User IDs, usernames or phone numbers * @internal */ -export async function deleteContacts( - this: TelegramClient, - userIds: InputPeerLike[] -): Promise +export async function deleteContacts(this: TelegramClient, userIds: InputPeerLike[]): Promise /** @internal */ export async function deleteContacts( @@ -41,16 +35,10 @@ export async function deleteContacts( const single = !Array.isArray(userIds) if (single) userIds = [userIds as InputPeerLike] - const inputPeers = await this.resolvePeerMany( - userIds as InputPeerLike[], - normalizeToInputUser, - ) + const inputPeers = await this.resolvePeerMany(userIds as InputPeerLike[], normalizeToInputUser) if (single && !inputPeers.length) { - throw new MtInvalidPeerTypeError( - (userIds as InputPeerLike[])[0], - 'user', - ) + throw new MtInvalidPeerTypeError((userIds as InputPeerLike[])[0], 'user') } const res = await this.call({ diff --git a/packages/client/src/methods/dialogs/_init-conversation.ts b/packages/client/src/methods/dialogs/_init-conversation.ts index de0a4023..8a62d274 100644 --- a/packages/client/src/methods/dialogs/_init-conversation.ts +++ b/packages/client/src/methods/dialogs/_init-conversation.ts @@ -17,11 +17,7 @@ function _initializeConversation(this: TelegramClient) { } /** @internal */ -export function _pushConversationMessage( - this: TelegramClient, - msg: Message, - incoming = false, -): void { +export function _pushConversationMessage(this: TelegramClient, msg: Message, incoming = false): void { // shortcut if (!this._hasConversations) return diff --git a/packages/client/src/methods/dialogs/delete-folder.ts b/packages/client/src/methods/dialogs/delete-folder.ts index 4a5262dd..28211ef4 100644 --- a/packages/client/src/methods/dialogs/delete-folder.ts +++ b/packages/client/src/methods/dialogs/delete-folder.ts @@ -8,10 +8,7 @@ import { TelegramClient } from '../../client' * @param id Folder ID or folder itself * @internal */ -export async function deleteFolder( - this: TelegramClient, - id: number | tl.RawDialogFilter, -): Promise { +export async function deleteFolder(this: TelegramClient, id: number | tl.RawDialogFilter): Promise { await this.call({ _: 'messages.updateDialogFilter', id: typeof id === 'number' ? id : id.id, diff --git a/packages/client/src/methods/dialogs/edit-folder.ts b/packages/client/src/methods/dialogs/edit-folder.ts index 8697b7fb..6a56bde5 100644 --- a/packages/client/src/methods/dialogs/edit-folder.ts +++ b/packages/client/src/methods/dialogs/edit-folder.ts @@ -25,11 +25,7 @@ export async function editFolder( } if (typeof folder === 'number' || typeof folder === 'string') { const old = await this.getFolders() - const found = old.find( - (it) => - it._ === 'dialogFilter' && - (it.id === folder || it.title === folder), - ) + const found = old.find((it) => it._ === 'dialogFilter' && (it.id === folder || it.title === folder)) if (!found) { throw new MtArgumentError(`Could not find a folder ${folder}`) diff --git a/packages/client/src/methods/dialogs/get-dialogs.ts b/packages/client/src/methods/dialogs/get-dialogs.ts index 716c76f4..73d63ad8 100644 --- a/packages/client/src/methods/dialogs/get-dialogs.ts +++ b/packages/client/src/methods/dialogs/get-dialogs.ts @@ -122,10 +122,7 @@ export async function* getDialogs( // fetch folder if needed let filters: tl.TypeDialogFilter | undefined - if ( - typeof params.folder === 'string' || - typeof params.folder === 'number' - ) { + if (typeof params.folder === 'string' || typeof params.folder === 'number') { const folders = await this.getFolders() const found = folders.find((it) => { if (it._ === 'dialogFilterDefault') { @@ -157,38 +154,28 @@ export async function* getDialogs( } } - const fetchPinnedDialogsFromFolder = - async (): Promise => { - if ( - !filters || - filters._ === 'dialogFilterDefault' || - !filters.pinnedPeers.length - ) { - return null - } - const res = await this.call({ - _: 'messages.getPeerDialogs', - peers: filters.pinnedPeers.map((peer) => ({ - _: 'inputDialogPeer', - peer, - })), - }) - - res.dialogs.forEach( - (dialog: tl.Mutable) => (dialog.pinned = true), - ) - - return res + const fetchPinnedDialogsFromFolder = async (): Promise => { + if (!filters || filters._ === 'dialogFilterDefault' || !filters.pinnedPeers.length) { + return null } + const res = await this.call({ + _: 'messages.getPeerDialogs', + peers: filters.pinnedPeers.map((peer) => ({ + _: 'inputDialogPeer', + peer, + })), + }) + + res.dialogs.forEach((dialog: tl.Mutable) => (dialog.pinned = true)) + + return res + } const pinned = params.pinned ?? 'include' let archived = params.archived ?? 'exclude' if (filters) { - archived = - filters._ !== 'dialogFilterDefault' && filters.excludeArchived ? - 'exclude' : - 'keep' + archived = filters._ !== 'dialogFilterDefault' && filters.excludeArchived ? 'exclude' : 'keep' } if (pinned === 'only') { @@ -215,12 +202,7 @@ export async function* getDialogs( let offsetDate = normalizeDate(params.offsetDate) ?? 0 let offsetPeer = params.offsetPeer ?? { _: 'inputPeerEmpty' } - if ( - filters && - filters._ !== 'dialogFilterDefault' && - filters.pinnedPeers.length && - pinned === 'include' - ) { + if (filters && filters._ !== 'dialogFilterDefault' && filters.pinnedPeers.length && pinned === 'include') { const res = await fetchPinnedDialogsFromFolder() if (res) { @@ -238,9 +220,7 @@ export async function* getDialogs( // 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 + const filterFolder = filters ? Dialog.filterFolder(filters, pinned !== 'keep') : undefined let folderId diff --git a/packages/client/src/methods/dialogs/get-folders.ts b/packages/client/src/methods/dialogs/get-folders.ts index f365847d..6bfa8301 100644 --- a/packages/client/src/methods/dialogs/get-folders.ts +++ b/packages/client/src/methods/dialogs/get-folders.ts @@ -6,9 +6,7 @@ import { TelegramClient } from '../../client' * Get list of folders. * @internal */ -export async function getFolders( - this: TelegramClient, -): Promise { +export async function getFolders(this: TelegramClient): Promise { return this.call({ _: 'messages.getDialogFilters', }) diff --git a/packages/client/src/methods/dialogs/get-peer-dialogs.ts b/packages/client/src/methods/dialogs/get-peer-dialogs.ts index 79339a24..428999b7 100644 --- a/packages/client/src/methods/dialogs/get-peer-dialogs.ts +++ b/packages/client/src/methods/dialogs/get-peer-dialogs.ts @@ -9,20 +9,14 @@ import { Dialog, InputPeerLike } from '../../types' * @param peers Peers for which to fetch dialogs. * @internal */ -export async function getPeerDialogs( - this: TelegramClient, - peers: InputPeerLike -): Promise +export async function getPeerDialogs(this: TelegramClient, peers: InputPeerLike): Promise /** * Get dialogs with certain peers. * * @param peers Peers for which to fetch dialogs. * @internal */ -export async function getPeerDialogs( - this: TelegramClient, - peers: InputPeerLike[] -): Promise +export async function getPeerDialogs(this: TelegramClient, peers: InputPeerLike[]): Promise /** * @internal @@ -36,12 +30,11 @@ export async function getPeerDialogs( const res = await this.call({ _: 'messages.getPeerDialogs', - peers: await this.resolvePeerMany(peers as InputPeerLike[]).then( - (peers) => - peers.map((it) => ({ - _: 'inputDialogPeer', - peer: it, - })), + peers: await this.resolvePeerMany(peers as InputPeerLike[]).then((peers) => + peers.map((it) => ({ + _: 'inputDialogPeer', + peer: it, + })), ), }) diff --git a/packages/client/src/methods/dialogs/set-folders.ts b/packages/client/src/methods/dialogs/set-folders.ts index d70301a9..b9386c2c 100644 --- a/packages/client/src/methods/dialogs/set-folders.ts +++ b/packages/client/src/methods/dialogs/set-folders.ts @@ -7,10 +7,7 @@ import { TelegramClient } from '../../client' * * @internal */ -export async function setFoldersOrder( - this: TelegramClient, - order: number[], -): Promise { +export async function setFoldersOrder(this: TelegramClient, order: number[]): Promise { await this.call({ _: 'messages.updateDialogFiltersOrder', order, diff --git a/packages/client/src/methods/files/download-buffer.ts b/packages/client/src/methods/files/download-buffer.ts index 14ac99e4..d31036ba 100644 --- a/packages/client/src/methods/files/download-buffer.ts +++ b/packages/client/src/methods/files/download-buffer.ts @@ -10,14 +10,8 @@ import { FileDownloadParameters, FileLocation } from '../../types' * @param params File download parameters * @internal */ -export async function downloadAsBuffer( - this: TelegramClient, - params: FileDownloadParameters, -): Promise { - if ( - params.location instanceof FileLocation && - Buffer.isBuffer(params.location.location) - ) { +export async function downloadAsBuffer(this: TelegramClient, params: FileDownloadParameters): Promise { + if (params.location instanceof FileLocation && Buffer.isBuffer(params.location.location)) { return params.location.location } diff --git a/packages/client/src/methods/files/download-file.ts b/packages/client/src/methods/files/download-file.ts index 111ba576..552100ed 100644 --- a/packages/client/src/methods/files/download-file.ts +++ b/packages/client/src/methods/files/download-file.ts @@ -16,21 +16,12 @@ try { * @param params File download parameters * @internal */ -export function downloadToFile( - this: TelegramClient, - filename: string, - params: FileDownloadParameters, -): Promise { +export function downloadToFile(this: TelegramClient, filename: string, params: FileDownloadParameters): Promise { if (!fs) { - throw new MtUnsupportedError( - 'Downloading to file is only supported in NodeJS', - ) + throw new MtUnsupportedError('Downloading to file is only supported in NodeJS') } - if ( - params.location instanceof FileLocation && - Buffer.isBuffer(params.location.location) - ) { + if (params.location instanceof FileLocation && Buffer.isBuffer(params.location.location)) { // early return for inline files const buf = params.location.location @@ -46,10 +37,6 @@ export function downloadToFile( const stream = this.downloadAsStream(params) return new Promise((resolve, reject) => { - stream - .on('error', reject) - .pipe(output) - .on('finish', resolve) - .on('error', reject) + stream.on('error', reject).pipe(output).on('finish', resolve).on('error', reject) }) } diff --git a/packages/client/src/methods/files/download-iterable.ts b/packages/client/src/methods/files/download-iterable.ts index d4632775..a67b2aad 100644 --- a/packages/client/src/methods/files/download-iterable.ts +++ b/packages/client/src/methods/files/download-iterable.ts @@ -1,14 +1,6 @@ -import { - ConnectionKind, - MtArgumentError, - MtUnsupportedError, -} from '@mtcute/core' +import { ConnectionKind, MtArgumentError, MtUnsupportedError } from '@mtcute/core' import { ConditionVariable } from '@mtcute/core/utils' -import { - fileIdToInputFileLocation, - fileIdToInputWebFileLocation, - parseFileId, -} from '@mtcute/file-id' +import { fileIdToInputFileLocation, fileIdToInputWebFileLocation, parseFileId } from '@mtcute/file-id' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' @@ -36,9 +28,7 @@ export async function* downloadAsIterable( const offset = params.offset ?? 0 if (offset % 4096 !== 0) { - throw new MtArgumentError( - `Invalid offset: ${offset}. Must be divisible by 4096`, - ) + throw new MtArgumentError(`Invalid offset: ${offset}. Must be divisible by 4096`) } let dcId = params.dcId @@ -76,13 +66,10 @@ export async function* downloadAsIterable( // we will receive a FileMigrateError in case this is invalid if (!dcId) dcId = this._defaultDcs.main.id - const partSizeKb = - params.partSize ?? (fileSize ? determinePartSize(fileSize) : 64) + const partSizeKb = params.partSize ?? (fileSize ? determinePartSize(fileSize) : 64) if (partSizeKb % 4 !== 0) { - throw new MtArgumentError( - `Invalid part size: ${partSizeKb}. Must be divisible by 4.`, - ) + throw new MtArgumentError(`Invalid part size: ${partSizeKb}. Must be divisible by 4.`) } const chunkSize = partSizeKb * 1024 @@ -90,10 +77,7 @@ export async function* downloadAsIterable( let limitBytes = params.limit ?? fileSize ?? Infinity if (limitBytes === 0) return - let numChunks = - limitBytes === Infinity ? - Infinity : - ~~((limitBytes + chunkSize - offset - 1) / chunkSize) + let numChunks = limitBytes === Infinity ? Infinity : ~~((limitBytes + chunkSize - offset - 1) / chunkSize) let nextChunkIdx = 0 let nextWorkerChunkIdx = 0 @@ -104,8 +88,7 @@ export async function* downloadAsIterable( let connectionKind: ConnectionKind if (isSmall) { - connectionKind = - dcId === this.network.getPrimaryDcId() ? 'main' : 'downloadSmall' + connectionKind = dcId === this.network.getPrimaryDcId() ? 'main' : 'downloadSmall' } else { connectionKind = 'download' } @@ -119,12 +102,8 @@ export async function* downloadAsIterable( poolSize, ) - const downloadChunk = async ( - chunk = nextWorkerChunkIdx++, - ): Promise => { - let result: - | tl.RpcCallReturn['upload.getFile'] - | tl.RpcCallReturn['upload.getWebFile'] + const downloadChunk = async (chunk = nextWorkerChunkIdx++): Promise => { + let result: tl.RpcCallReturn['upload.getFile'] | tl.RpcCallReturn['upload.getWebFile'] try { result = await this.call( @@ -155,16 +134,10 @@ export async function* downloadAsIterable( // we shouldnt receive them since cdnSupported is not set in the getFile request. // also, i couldnt find any media that would be downloaded from cdn, so even if // i implemented that, i wouldnt be able to test that, so :shrug: - throw new MtUnsupportedError( - 'Received CDN redirect, which is not supported (yet)', - ) + throw new MtUnsupportedError('Received CDN redirect, which is not supported (yet)') } - if ( - result._ === 'upload.webFile' && - result.size && - limitBytes === Infinity - ) { + if (result._ === 'upload.webFile' && result.size && limitBytes === Infinity) { limitBytes = result.size numChunks = ~~((limitBytes + chunkSize - offset - 1) / chunkSize) } @@ -175,21 +148,13 @@ export async function* downloadAsIterable( nextChunkCv.notify() } - if ( - nextWorkerChunkIdx < numChunks && - result.bytes.length === chunkSize - ) { + if (nextWorkerChunkIdx < numChunks && result.bytes.length === chunkSize) { return downloadChunk() } } let error: unknown = undefined - void Promise.all( - Array.from( - { length: Math.min(poolSize * REQUESTS_PER_CONNECTION, numChunks) }, - downloadChunk, - ), - ) + void Promise.all(Array.from({ length: Math.min(poolSize * REQUESTS_PER_CONNECTION, numChunks) }, downloadChunk)) .catch((e) => { this.log.debug('download workers errored: %s', e.message) error = e diff --git a/packages/client/src/methods/files/download-stream.ts b/packages/client/src/methods/files/download-stream.ts index 8a98936e..8b86cbfe 100644 --- a/packages/client/src/methods/files/download-stream.ts +++ b/packages/client/src/methods/files/download-stream.ts @@ -11,14 +11,8 @@ import { bufferToStream } from '../../utils/stream-utils' * @param params File download parameters * @internal */ -export function downloadAsStream( - this: TelegramClient, - params: FileDownloadParameters, -): Readable { - if ( - params.location instanceof FileLocation && - Buffer.isBuffer(params.location.location) - ) { +export function downloadAsStream(this: TelegramClient, params: FileDownloadParameters): Readable { + if (params.location instanceof FileLocation && Buffer.isBuffer(params.location.location)) { return bufferToStream(params.location.location) } diff --git a/packages/client/src/methods/files/normalize-input-file.ts b/packages/client/src/methods/files/normalize-input-file.ts index ce211bb0..af4c550b 100644 --- a/packages/client/src/methods/files/normalize-input-file.ts +++ b/packages/client/src/methods/files/normalize-input-file.ts @@ -22,9 +22,7 @@ export async function _normalizeInputFile( }, ): Promise { if (typeof input === 'object' && tl.isAnyInputMedia(input)) { - throw new MtArgumentError( - "InputFile can't be created from an InputMedia", - ) + throw new MtArgumentError("InputFile can't be created from an InputMedia") } else if (tdFileId.isFileIdLike(input)) { if (typeof input === 'string' && input.match(/^file:/)) { const uploaded = await this.uploadFile({ @@ -34,9 +32,7 @@ export async function _normalizeInputFile( return uploaded.inputFile } - throw new MtArgumentError( - "InputFile can't be created from an URL or a File ID", - ) + throw new MtArgumentError("InputFile can't be created from an URL or a File ID") } else if (isUploadedFile(input)) { return input.inputFile } else if (typeof input === 'object' && tl.isAnyInputFile(input)) { diff --git a/packages/client/src/methods/files/normalize-input-media.ts b/packages/client/src/methods/files/normalize-input-media.ts index 317a0461..a027e9c5 100644 --- a/packages/client/src/methods/files/normalize-input-media.ts +++ b/packages/client/src/methods/files/normalize-input-media.ts @@ -1,12 +1,7 @@ import Long from 'long' import { assertTypeIs } from '@mtcute/core/utils' -import { - fileIdToInputDocument, - fileIdToInputPhoto, - parseFileId, - tdFileId, -} from '@mtcute/file-id' +import { fileIdToInputDocument, fileIdToInputPhoto, parseFileId, tdFileId } from '@mtcute/file-id' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' @@ -205,9 +200,7 @@ export async function _normalizeInputMedia( let sendMime if (media.type === 'sticker') { - sendMime = media.isAnimated ? - 'application/x-tgsticker' : - 'image/webp' + sendMime = media.isAnimated ? 'application/x-tgsticker' : 'image/webp' } else { sendMime = media.fileMime } @@ -225,10 +218,7 @@ export async function _normalizeInputMedia( const uploadPeer = params.uploadPeer ?? { _: 'inputPeerSelf' } - const uploadMediaIfNeeded = async ( - inputMedia: tl.TypeInputMedia, - photo: boolean, - ): Promise => { + const uploadMediaIfNeeded = async (inputMedia: tl.TypeInputMedia, photo: boolean): Promise => { if (!uploadMedia) return inputMedia const res = await this.call({ @@ -238,16 +228,8 @@ export async function _normalizeInputMedia( }) if (photo) { - assertTypeIs( - 'normalizeInputMedia (@ messages.uploadMedia)', - res, - 'messageMediaPhoto', - ) - assertTypeIs( - 'normalizeInputMedia (@ messages.uploadMedia)', - res.photo!, - 'photo', - ) + assertTypeIs('normalizeInputMedia (@ messages.uploadMedia)', res, 'messageMediaPhoto') + assertTypeIs('normalizeInputMedia (@ messages.uploadMedia)', res.photo!, 'photo') return { _: 'inputMediaPhoto', @@ -260,16 +242,8 @@ export async function _normalizeInputMedia( ttlSeconds: media.ttlSeconds, } } - assertTypeIs( - 'normalizeInputMedia (@ messages.uploadMedia)', - res, - 'messageMediaDocument', - ) - assertTypeIs( - 'normalizeInputMedia (@ messages.uploadMedia)', - res.document!, - 'document', - ) + assertTypeIs('normalizeInputMedia (@ messages.uploadMedia)', res, 'messageMediaDocument') + assertTypeIs('normalizeInputMedia (@ messages.uploadMedia)', res.document!, 'document') return { _: 'inputMediaDocument', @@ -289,10 +263,7 @@ export async function _normalizeInputMedia( if (typeof input === 'string' && input.match(/^https?:\/\//)) { return uploadMediaIfNeeded( { - _: - media.type === 'photo' ? - 'inputMediaPhotoExternal' : - 'inputMediaDocumentExternal', + _: media.type === 'photo' ? 'inputMediaPhotoExternal' : 'inputMediaDocumentExternal', url: input, }, media.type === 'photo', @@ -300,8 +271,7 @@ export async function _normalizeInputMedia( } else if (typeof input === 'string' && input.match(/^file:/)) { await upload(input.substring(5)) } else { - const parsed = - typeof input === 'string' ? parseFileId(input) : input + const parsed = typeof input === 'string' ? parseFileId(input) : input if (parsed.location._ === 'photo') { return { @@ -359,11 +329,7 @@ export async function _normalizeInputMedia( if (media.type !== 'voice') { attributes.push({ _: 'documentAttributeFilename', - fileName: - media.fileName || - (typeof media.file === 'string' ? - extractFileName(media.file) : - 'unnamed'), + fileName: media.fileName || (typeof media.file === 'string' ? extractFileName(media.file) : 'unnamed'), }) } @@ -389,10 +355,7 @@ export async function _normalizeInputMedia( duration: media.duration || 0, title: media.type === 'audio' ? media.title : undefined, performer: media.type === 'audio' ? media.performer : undefined, - waveform: - media.type === 'voice' && media.waveform ? - encodeWaveform(media.waveform) : - undefined, + waveform: media.type === 'voice' && media.waveform ? encodeWaveform(media.waveform) : undefined, }) } diff --git a/packages/client/src/methods/files/upload-file.ts b/packages/client/src/methods/files/upload-file.ts index aa5e1cdd..5d0b182b 100644 --- a/packages/client/src/methods/files/upload-file.ts +++ b/packages/client/src/methods/files/upload-file.ts @@ -9,11 +9,7 @@ import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { UploadedFile, UploadFileLike } from '../../types' import { determinePartSize, isProbablyPlainText } from '../../utils/file-utils' -import { - bufferToStream, - convertWebStreamToNodeReadable, - readBytesFromStream, -} from '../../utils/stream-utils' +import { bufferToStream, convertWebStreamToNodeReadable, readBytesFromStream } from '../../utils/stream-utils' let fs: typeof import('fs') | null = null let path: typeof import('path') | null = null @@ -124,9 +120,7 @@ export async function uploadFile( if (typeof file === 'string') { if (!fs) { - throw new MtArgumentError( - 'Local paths are only supported for NodeJS!', - ) + throw new MtArgumentError('Local paths are only supported for NodeJS!') } file = fs.createReadStream(file) } @@ -142,19 +136,11 @@ export async function uploadFile( // fs.ReadStream is a subclass of Readable, no conversion needed } - if ( - typeof ReadableStream !== 'undefined' && - file instanceof ReadableStream - ) { + if (typeof ReadableStream !== 'undefined' && file instanceof ReadableStream) { file = convertWebStreamToNodeReadable(file) } - if ( - typeof file === 'object' && - 'headers' in file && - 'body' in file && - 'url' in file - ) { + if (typeof file === 'object' && 'headers' in file && 'body' in file && 'url' in file) { // fetch() response const length = parseInt(file.headers.get('content-length') || '0') if (!isNaN(length) && length) fileSize = length @@ -186,10 +172,7 @@ export async function uploadFile( throw new MtArgumentError('Fetch response contains `null` body') } - if ( - typeof ReadableStream !== 'undefined' && - file.body instanceof ReadableStream - ) { + if (typeof ReadableStream !== 'undefined' && file.body instanceof ReadableStream) { file = convertWebStreamToNodeReadable(file.body) } else { file = file.body @@ -206,9 +189,7 @@ export async function uploadFile( if (!partSizeKb) { if (fileSize === -1) { - partSizeKb = params.estimatedSize ? - determinePartSize(params.estimatedSize) : - 64 + partSizeKb = params.estimatedSize ? determinePartSize(params.estimatedSize) : 64 } else { partSizeKb = determinePartSize(fileSize) } @@ -223,27 +204,18 @@ export async function uploadFile( } const partSize = partSizeKb * 1024 - let partCount = - fileSize === -1 ? -1 : ~~((fileSize + partSize - 1) / partSize) - const maxPartCount = this.network.params.isPremium ? - MAX_PART_COUNT_PREMIUM : - MAX_PART_COUNT + let partCount = fileSize === -1 ? -1 : ~~((fileSize + partSize - 1) / partSize) + const maxPartCount = this.network.params.isPremium ? MAX_PART_COUNT_PREMIUM : MAX_PART_COUNT if (partCount > maxPartCount) { - throw new MtArgumentError( - `File is too large (max ${maxPartCount} parts, got ${partCount})`, - ) + throw new MtArgumentError(`File is too large (max ${maxPartCount} parts, got ${partCount})`) } const isBig = fileSize === -1 || fileSize > BIG_FILE_MIN_SIZE const isSmall = fileSize !== -1 && fileSize < SMALL_FILE_MAX_SIZE const connectionKind = isSmall ? 'main' : 'upload' - const connectionPoolSize = Math.min( - this.network.getPoolSize(connectionKind), - partCount, - ) - const requestsPerConnection = - params.requestsPerConnection ?? REQUESTS_PER_CONNECTION + const connectionPoolSize = Math.min(this.network.getPoolSize(connectionKind), partCount) + const requestsPerConnection = params.requestsPerConnection ?? REQUESTS_PER_CONNECTION this.log.debug( 'uploading %d bytes file in %d chunks, each %d bytes in %s connection pool of size %d', @@ -278,26 +250,18 @@ export async function uploadFile( if (fileSize === -1 && stream.readableEnded) { fileSize = pos + (part?.length ?? 0) partCount = ~~((fileSize + partSize - 1) / partSize) - this.log.debug( - 'readable ended, file size = %d, part count = %d', - fileSize, - partCount, - ) + this.log.debug('readable ended, file size = %d, part count = %d', fileSize, partCount) } if (!part) { - throw new MtArgumentError( - `Unexpected EOS (there were only ${idx} parts, but expected ${partCount})`, - ) + throw new MtArgumentError(`Unexpected EOS (there were only ${idx} parts, but expected ${partCount})`) } if (!Buffer.isBuffer(part)) { throw new MtArgumentError(`Part ${thisIdx} was not a Buffer!`) } if (part.length > partSize) { - throw new MtArgumentError( - `Part ${thisIdx} had invalid size (expected ${partSize}, got ${part.length})`, - ) + throw new MtArgumentError(`Part ${thisIdx} had invalid size (expected ${partSize}, got ${part.length})`) } if (thisIdx === 0 && fileMime === undefined) { @@ -310,9 +274,7 @@ export async function uploadFile( // if all 8 bytes are printable ASCII characters, // the entire file is probably plain text const isPlainText = isProbablyPlainText(part.slice(0, 8)) - fileMime = isPlainText ? - 'text/plain' : - 'application/octet-stream' + fileMime = isPlainText ? 'text/plain' : 'application/octet-stream' } } diff --git a/packages/client/src/methods/files/upload-media.ts b/packages/client/src/methods/files/upload-media.ts index c6c584da..23165728 100644 --- a/packages/client/src/methods/files/upload-media.ts +++ b/packages/client/src/methods/files/upload-media.ts @@ -1,18 +1,8 @@ -import { - assertNever, - MtArgumentError, - MtTypeAssertionError, -} from '@mtcute/core' +import { assertNever, MtArgumentError, MtTypeAssertionError } from '@mtcute/core' import { assertTypeIs } from '@mtcute/core/utils' import { TelegramClient } from '../../client' -import { - InputMediaLike, - InputPeerLike, - MessageMedia, - Photo, - RawDocument, -} from '../../types' +import { InputMediaLike, InputPeerLike, MessageMedia, Photo, RawDocument } from '../../types' import { parseDocument } from '../../types/media/document-utils' /** @@ -72,11 +62,7 @@ export async function uploadMedia( }) if (res._ === 'messageMediaEmpty') { - throw new MtTypeAssertionError( - 'uploadMedia', - 'not messageMediaEmpty', - 'messageMediaEmpty', - ) + throw new MtTypeAssertionError('uploadMedia', 'not messageMediaEmpty', 'messageMediaEmpty') } switch (normMedia._) { diff --git a/packages/client/src/methods/invite-links/export-invite-link.ts b/packages/client/src/methods/invite-links/export-invite-link.ts index 6ce5eb1c..680bee95 100644 --- a/packages/client/src/methods/invite-links/export-invite-link.ts +++ b/packages/client/src/methods/invite-links/export-invite-link.ts @@ -11,10 +11,7 @@ import { ChatInviteLink, InputPeerLike } from '../../types' * @param chatId Chat IDs * @internal */ -export async function exportInviteLink( - this: TelegramClient, - chatId: InputPeerLike, -): Promise { +export async function exportInviteLink(this: TelegramClient, chatId: InputPeerLike): Promise { const res = await this.call({ _: 'messages.exportChatInvite', peer: await this.resolvePeer(chatId), diff --git a/packages/client/src/methods/invite-links/get-invite-link-members.ts b/packages/client/src/methods/invite-links/get-invite-link-members.ts index a9d10610..89d931ec 100644 --- a/packages/client/src/methods/invite-links/get-invite-link-members.ts +++ b/packages/client/src/methods/invite-links/get-invite-link-members.ts @@ -50,17 +50,16 @@ export async function* getInviteLinkMembers( for (;;) { // for some reason ts needs annotation, idk - const res: tl.RpcCallReturn['messages.getChatInviteImporters'] = - await this.call({ - _: 'messages.getChatInviteImporters', - limit: Math.min(100, limit - current), - peer, - link: params.link, - requested: params.requested, - q: params.requestedSearch, - offsetDate, - offsetUser, - }) + const res: tl.RpcCallReturn['messages.getChatInviteImporters'] = await this.call({ + _: 'messages.getChatInviteImporters', + limit: Math.min(100, limit - current), + peer, + link: params.link, + requested: params.requested, + q: params.requestedSearch, + offsetDate, + offsetUser, + }) if (!res.importers.length) break 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 057084c8..28a4303c 100644 --- a/packages/client/src/methods/invite-links/get-invite-links.ts +++ b/packages/client/src/methods/invite-links/get-invite-links.ts @@ -54,15 +54,14 @@ export async function* getInviteLinks( let offsetLink: string | undefined = undefined for (;;) { - const res: tl.RpcCallReturn['messages.getExportedChatInvites'] = - await this.call({ - _: 'messages.getExportedChatInvites', - peer, - adminId: admin, - limit: Math.min(chunkSize, total - current), - offsetDate, - offsetLink, - }) + const res: tl.RpcCallReturn['messages.getExportedChatInvites'] = await this.call({ + _: 'messages.getExportedChatInvites', + peer, + adminId: admin, + limit: Math.min(chunkSize, total - current), + offsetDate, + offsetLink, + }) if (!res.invites.length) break @@ -71,11 +70,7 @@ export async function* getInviteLinks( const last = res.invites[res.invites.length - 1] if (last._ === 'chatInvitePublicJoinRequests') { - throw new MtTypeAssertionError( - 'getInviteLinks', - 'chatInviteExported', - last._, - ) + throw new MtTypeAssertionError('getInviteLinks', 'chatInviteExported', last._) } offsetDate = last.date offsetLink = last.link 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 9b270c6c..4967ccaa 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 @@ -9,10 +9,7 @@ import { ChatInviteLink, InputPeerLike, PeersIndex } from '../../types' * @param chatId Chat ID * @internal */ -export async function getPrimaryInviteLink( - this: TelegramClient, - chatId: InputPeerLike, -): Promise { +export async function getPrimaryInviteLink(this: TelegramClient, chatId: InputPeerLike): Promise { const res = await this.call({ _: 'messages.getExportedChatInvites', peer: await this.resolvePeer(chatId), @@ -30,11 +27,7 @@ export async function getPrimaryInviteLink( } if (!res.invites[0].permanent) { - throw new MtTypeAssertionError( - 'messages.getExportedChatInvites (@ .invites[0].permanent)', - 'true', - 'false', - ) + throw new MtTypeAssertionError('messages.getExportedChatInvites (@ .invites[0].permanent)', 'true', 'false') } const peers = PeersIndex.from(res) diff --git a/packages/client/src/methods/invite-links/revoke-invite-link.ts b/packages/client/src/methods/invite-links/revoke-invite-link.ts index 2a8d42f8..da76ff4c 100644 --- a/packages/client/src/methods/invite-links/revoke-invite-link.ts +++ b/packages/client/src/methods/invite-links/revoke-invite-link.ts @@ -26,10 +26,7 @@ export async function revokeInviteLink( const peers = PeersIndex.from(res) - const invite = - res._ === 'messages.exportedChatInviteReplaced' ? - res.newInvite : - res.invite + const invite = res._ === 'messages.exportedChatInviteReplaced' ? res.newInvite : res.invite return new ChatInviteLink(this, invite, peers) } diff --git a/packages/client/src/methods/messages/close-poll.ts b/packages/client/src/methods/messages/close-poll.ts index 0954454f..d453f4e5 100644 --- a/packages/client/src/methods/messages/close-poll.ts +++ b/packages/client/src/methods/messages/close-poll.ts @@ -17,11 +17,7 @@ import { assertIsUpdatesGroup } from '../../utils/updates-utils' * @param message Message ID where this poll was found * @internal */ -export async function closePoll( - this: TelegramClient, - chatId: InputPeerLike, - message: number, -): Promise { +export async function closePoll(this: TelegramClient, chatId: InputPeerLike, message: number): Promise { const res = await this.call({ _: 'messages.editMessage', peer: await this.resolvePeer(chatId), @@ -43,18 +39,10 @@ export async function closePoll( this._handleUpdate(res, true) const upd = res.updates[0] - assertTypeIs( - 'messages.editMessage (@ .updates[0])', - upd, - 'updateMessagePoll', - ) + assertTypeIs('messages.editMessage (@ .updates[0])', upd, 'updateMessagePoll') if (!upd.poll) { - throw new MtTypeAssertionError( - 'messages.editMessage (@ .updates[0].poll)', - 'poll', - 'undefined', - ) + throw new MtTypeAssertionError('messages.editMessage (@ .updates[0].poll)', 'poll', 'undefined') } const peers = PeersIndex.from(res) diff --git a/packages/client/src/methods/messages/delete-messages.ts b/packages/client/src/methods/messages/delete-messages.ts index 88168b80..99ff9224 100644 --- a/packages/client/src/methods/messages/delete-messages.ts +++ b/packages/client/src/methods/messages/delete-messages.ts @@ -2,10 +2,7 @@ import { MaybeArray } from '@mtcute/core' import { TelegramClient } from '../../client' import { InputPeerLike } from '../../types' -import { - isInputPeerChannel, - normalizeToInputChannel, -} from '../../utils/peer-utils' +import { isInputPeerChannel, normalizeToInputChannel } from '../../utils/peer-utils' import { createDummyUpdate } from '../../utils/updates-utils' /** diff --git a/packages/client/src/methods/messages/edit-inline-message.ts b/packages/client/src/methods/messages/edit-inline-message.ts index ac6e6090..286861f3 100644 --- a/packages/client/src/methods/messages/edit-inline-message.ts +++ b/packages/client/src/methods/messages/edit-inline-message.ts @@ -1,12 +1,7 @@ import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - BotKeyboard, - FormattedString, - InputMediaLike, - ReplyMarkup, -} from '../../types' +import { BotKeyboard, FormattedString, InputMediaLike, ReplyMarkup } from '../../types' import { normalizeInlineId } from '../../utils/inline-utils' /** @@ -91,11 +86,7 @@ export async function editInlineMessage( ) } } else if (params.text) { - [content, entities] = await this._parseEntities( - params.text, - params.parseMode, - params.entities, - ) + [content, entities] = await this._parseEntities(params.text, params.parseMode, params.entities) } let retries = 3 diff --git a/packages/client/src/methods/messages/edit-message.ts b/packages/client/src/methods/messages/edit-message.ts index 597a9920..c5925d64 100644 --- a/packages/client/src/methods/messages/edit-message.ts +++ b/packages/client/src/methods/messages/edit-message.ts @@ -1,14 +1,7 @@ import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - BotKeyboard, - FormattedString, - InputMediaLike, - InputPeerLike, - Message, - ReplyMarkup, -} from '../../types' +import { BotKeyboard, FormattedString, InputMediaLike, InputPeerLike, Message, ReplyMarkup } from '../../types' /** * Edit message text, media, reply markup and schedule date. @@ -96,11 +89,7 @@ export async function editMessage( ) } } else if (params.text) { - [content, entities] = await this._parseEntities( - params.text, - params.parseMode, - params.entities, - ) + [content, entities] = await this._parseEntities(params.text, params.parseMode, params.entities) } const res = await this.call({ diff --git a/packages/client/src/methods/messages/find-in-update.ts b/packages/client/src/methods/messages/find-in-update.ts index b03095ab..aa45def3 100644 --- a/packages/client/src/methods/messages/find-in-update.ts +++ b/packages/client/src/methods/messages/find-in-update.ts @@ -6,20 +6,14 @@ import { Message, PeersIndex } from '../../types' import { assertIsUpdatesGroup } from '../../utils/updates-utils' /** @internal */ -export function _findMessageInUpdate( - this: TelegramClient, - res: tl.TypeUpdates, - isEdit = false, -): Message { +export function _findMessageInUpdate(this: TelegramClient, res: tl.TypeUpdates, isEdit = false): Message { assertIsUpdatesGroup('_findMessageInUpdate', res) this._handleUpdate(res, true) for (const u of res.updates) { if ( - (isEdit && - (u._ === 'updateEditMessage' || - u._ === 'updateEditChannelMessage')) || + (isEdit && (u._ === 'updateEditMessage' || u._ === 'updateEditChannelMessage')) || (!isEdit && (u._ === 'updateNewMessage' || u._ === 'updateNewChannelMessage' || @@ -27,12 +21,7 @@ export function _findMessageInUpdate( ) { const peers = PeersIndex.from(res) - return new Message( - this, - u.message, - peers, - u._ === 'updateNewScheduledMessage', - ) + return new Message(this, u.message, peers, u._ === 'updateNewScheduledMessage') } } diff --git a/packages/client/src/methods/messages/forward-messages.ts b/packages/client/src/methods/messages/forward-messages.ts index 747ed467..edc02394 100644 --- a/packages/client/src/methods/messages/forward-messages.ts +++ b/packages/client/src/methods/messages/forward-messages.ts @@ -3,13 +3,7 @@ import { randomLong } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - FormattedString, - InputMediaLike, - InputPeerLike, - Message, - PeersIndex, -} from '../../types' +import { FormattedString, InputMediaLike, InputPeerLike, Message, PeersIndex } from '../../types' import { normalizeDate } from '../../utils/misc-utils' import { assertIsUpdatesGroup } from '../../utils/updates-utils' @@ -104,7 +98,7 @@ export async function forwardMessages( * have content protection. */ forbidForwards?: boolean - } + }, ): Promise /** @@ -201,7 +195,7 @@ export async function forwardMessages( * have content protection. */ forbidForwards?: boolean - } + }, ): Promise> /** @internal */ @@ -303,9 +297,7 @@ export async function forwardMessages( // error, instead only first 100 IDs will be forwarded, // which is definitely not the best outcome. if (messages.length > 100) { - throw new MtArgumentError( - 'You can forward no more than 100 messages at once', - ) + throw new MtArgumentError('You can forward no more than 100 messages at once') } const toPeer = await this.resolvePeer(toChatId) @@ -314,9 +306,7 @@ export async function forwardMessages( if (params.caption) { if (params.captionMedia) { - throw new MtArgumentError( - 'You can either pass `caption` or `captionMedia`', - ) + throw new MtArgumentError('You can either pass `caption` or `captionMedia`') } captionMessage = await this.sendText(toPeer, params.caption, { @@ -350,9 +340,7 @@ export async function forwardMessages( dropAuthor: params.noAuthor, dropMediaCaptions: params.noCaption, noforwards: params.forbidForwards, - sendAs: params.sendAs ? - await this.resolvePeer(params.sendAs) : - undefined, + sendAs: params.sendAs ? await this.resolvePeer(params.sendAs) : undefined, }) assertIsUpdatesGroup('messages.forwardMessages', res) @@ -367,14 +355,7 @@ export async function forwardMessages( case 'updateNewMessage': case 'updateNewChannelMessage': case 'updateNewScheduledMessage': - forwarded.push( - new Message( - this, - upd.message, - peers, - upd._ === 'updateNewScheduledMessage', - ), - ) + forwarded.push(new Message(this, upd.message, peers, upd._ === 'updateNewScheduledMessage')) break } }) diff --git a/packages/client/src/methods/messages/get-discussion-message.ts b/packages/client/src/methods/messages/get-discussion-message.ts index fb63fe7c..090598a0 100644 --- a/packages/client/src/methods/messages/get-discussion-message.ts +++ b/packages/client/src/methods/messages/get-discussion-message.ts @@ -23,9 +23,7 @@ export async function _getDiscussionMessage( } const msg = res.messages[0] - const chat = res.chats.find( - (it) => it.id === (msg.peerId as tl.RawPeerChannel).channelId, - )! as tl.RawChannel + const chat = res.chats.find((it) => it.id === (msg.peerId as tl.RawPeerChannel).channelId)! as tl.RawChannel return [ { diff --git a/packages/client/src/methods/messages/get-history.ts b/packages/client/src/methods/messages/get-history.ts index f92b3f59..a90e76c3 100644 --- a/packages/client/src/methods/messages/get-history.ts +++ b/packages/client/src/methods/messages/get-history.ts @@ -84,13 +84,10 @@ export async function* getHistory( const minId = params.minId || 0 const maxId = params.maxId || 0 - let offsetId = - params.offsetId ?? (params.reverse && !params.offsetDate ? 1 : 0) + let offsetId = params.offsetId ?? (params.reverse && !params.offsetDate ? 1 : 0) const offsetDate = normalizeDate(params.offsetDate) || 0 const baseOffset = -(params.reverse ? limit : 0) - let addOffset = - (params.offset ? params.offset * (params.reverse ? -1 : 1) : 0) + - baseOffset + let addOffset = (params.offset ? params.offset * (params.reverse ? -1 : 1) : 0) + baseOffset // resolve peer once and pass an InputPeer afterwards const peer = await this.resolvePeer(chatId) @@ -109,18 +106,12 @@ export async function* getHistory( }) if (res._ === 'messages.messagesNotModified') { - throw new MtTypeAssertionError( - 'messages.getHistory', - '!messages.messagesNotModified', - res._, - ) + throw new MtTypeAssertionError('messages.getHistory', '!messages.messagesNotModified', res._) } const peers = PeersIndex.from(res) - const msgs = res.messages - .filter((msg) => msg._ !== 'messageEmpty') - .map((msg) => new Message(this, msg, peers)) + const msgs = res.messages.filter((msg) => msg._ !== 'messageEmpty').map((msg) => new Message(this, msg, peers)) if (!msgs.length) break diff --git a/packages/client/src/methods/messages/get-message-group.ts b/packages/client/src/methods/messages/get-message-group.ts index a2e6ee3f..e2bf41f4 100644 --- a/packages/client/src/methods/messages/get-message-group.ts +++ b/packages/client/src/methods/messages/get-message-group.ts @@ -37,7 +37,5 @@ export async function getMessageGroup( if (!groupedId) throw new MtArgumentError('This message is not grouped') - return messages.filter( - (it) => it && it.groupedId?.eq(groupedId), - ) as Message[] + return messages.filter((it) => it && it.groupedId?.eq(groupedId)) as Message[] } diff --git a/packages/client/src/methods/messages/get-message-reactions.ts b/packages/client/src/methods/messages/get-message-reactions.ts index fcc74701..23171113 100644 --- a/packages/client/src/methods/messages/get-message-reactions.ts +++ b/packages/client/src/methods/messages/get-message-reactions.ts @@ -20,7 +20,7 @@ import { assertIsUpdatesGroup } from '../../utils/updates-utils' export async function getMessageReactions( this: TelegramClient, chatId: InputPeerLike, - messages: number + messages: number, ): Promise /** @@ -38,7 +38,7 @@ export async function getMessageReactions( export async function getMessageReactions( this: TelegramClient, chatId: InputPeerLike, - messages: number[] + messages: number[], ): Promise<(MessageReactions | null)[]> /** @@ -74,11 +74,7 @@ export async function getMessageReactions( const peers = PeersIndex.from(res) for (const update of res.updates) { - assertTypeIs( - 'messages.getMessagesReactions', - update, - 'updateMessageReactions', - ) + assertTypeIs('messages.getMessagesReactions', update, 'updateMessageReactions') index[update.msgId] = new MessageReactions( this, diff --git a/packages/client/src/methods/messages/get-messages-unsafe.ts b/packages/client/src/methods/messages/get-messages-unsafe.ts index dce148b3..ea992eec 100644 --- a/packages/client/src/methods/messages/get-messages-unsafe.ts +++ b/packages/client/src/methods/messages/get-messages-unsafe.ts @@ -20,7 +20,7 @@ import { Message, PeersIndex } from '../../types' export async function getMessagesUnsafe( this: TelegramClient, messageId: number, - fromReply?: boolean + fromReply?: boolean, ): Promise /** * Get messages from PM or legacy group by their IDs. @@ -41,7 +41,7 @@ export async function getMessagesUnsafe( export async function getMessagesUnsafe( this: TelegramClient, messageIds: number[], - fromReply?: boolean + fromReply?: boolean, ): Promise<(Message | null)[]> /** @internal */ @@ -65,11 +65,7 @@ export async function getMessagesUnsafe( }) if (res._ === 'messages.messagesNotModified') { - throw new MtTypeAssertionError( - 'getMessages', - '!messages.messagesNotModified', - res._, - ) + throw new MtTypeAssertionError('getMessages', '!messages.messagesNotModified', res._) } const peers = PeersIndex.from(res) diff --git a/packages/client/src/methods/messages/get-messages.ts b/packages/client/src/methods/messages/get-messages.ts index 49bb5ecd..b310e39e 100644 --- a/packages/client/src/methods/messages/get-messages.ts +++ b/packages/client/src/methods/messages/get-messages.ts @@ -3,10 +3,7 @@ import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { InputPeerLike, Message, PeersIndex } from '../../types' -import { - isInputPeerChannel, - normalizeToInputChannel, -} from '../../utils/peer-utils' +import { isInputPeerChannel, normalizeToInputChannel } from '../../utils/peer-utils' /** * Get a single message in chat by its ID @@ -22,7 +19,7 @@ export async function getMessages( this: TelegramClient, chatId: InputPeerLike, messageId: number, - fromReply?: boolean + fromReply?: boolean, ): Promise /** * Get messages in chat by their IDs @@ -41,7 +38,7 @@ export async function getMessages( this: TelegramClient, chatId: InputPeerLike, messageIds: number[], - fromReply?: boolean + fromReply?: boolean, ): Promise<(Message | null)[]> /** @internal */ @@ -78,11 +75,7 @@ export async function getMessages( ) if (res._ === 'messages.messagesNotModified') { - throw new MtTypeAssertionError( - 'getMessages', - '!messages.messagesNotModified', - res._, - ) + throw new MtTypeAssertionError('getMessages', '!messages.messagesNotModified', res._) } const peers = PeersIndex.from(res) @@ -95,33 +88,18 @@ export async function getMessages( // (channels have their own message numbering) switch (peer._) { case 'inputPeerSelf': - if ( - !( - msg.peerId._ === 'peerUser' && - msg.peerId.userId === this._userId - ) - ) { + if (!(msg.peerId._ === 'peerUser' && msg.peerId.userId === this._userId)) { return null } break case 'inputPeerUser': case 'inputPeerUserFromMessage': - if ( - !( - msg.peerId._ === 'peerUser' && - msg.peerId.userId === peer.userId - ) - ) { + if (!(msg.peerId._ === 'peerUser' && msg.peerId.userId === peer.userId)) { return null } break case 'inputPeerChat': - if ( - !( - msg.peerId._ === 'peerChat' && - msg.peerId.chatId === peer.chatId - ) - ) { + if (!(msg.peerId._ === 'peerChat' && msg.peerId.chatId === peer.chatId)) { return null } break diff --git a/packages/client/src/methods/messages/get-reaction-users.ts b/packages/client/src/methods/messages/get-reaction-users.ts index a809fd4f..4b2c26c2 100644 --- a/packages/client/src/methods/messages/get-reaction-users.ts +++ b/packages/client/src/methods/messages/get-reaction-users.ts @@ -69,15 +69,14 @@ export async function* getReactionUsers( } for (;;) { - const res: tl.RpcCallReturn['messages.getMessageReactionsList'] = - await this.call({ - _: 'messages.getMessageReactionsList', - peer, - id: messageId, - reaction, - limit: Math.min(chunkSize, total - current), - offset, - }) + const res: tl.RpcCallReturn['messages.getMessageReactionsList'] = await this.call({ + _: 'messages.getMessageReactionsList', + peer, + id: messageId, + reaction, + limit: Math.min(chunkSize, total - current), + offset, + }) if (!res.reactions.length) break diff --git a/packages/client/src/methods/messages/get-scheduled-messages.ts b/packages/client/src/methods/messages/get-scheduled-messages.ts index 2094fc54..d9c1abfb 100644 --- a/packages/client/src/methods/messages/get-scheduled-messages.ts +++ b/packages/client/src/methods/messages/get-scheduled-messages.ts @@ -13,7 +13,7 @@ import { InputPeerLike, Message, PeersIndex } from '../../types' export async function getScheduledMessages( this: TelegramClient, chatId: InputPeerLike, - messageId: number + messageId: number, ): Promise /** * Get scheduled messages in chat by their IDs @@ -28,7 +28,7 @@ export async function getScheduledMessages( export async function getScheduledMessages( this: TelegramClient, chatId: InputPeerLike, - messageIds: number[] + messageIds: number[], ): Promise<(Message | null)[]> /** @internal */ @@ -49,11 +49,7 @@ export async function getScheduledMessages( }) if (res._ === 'messages.messagesNotModified') { - throw new MtTypeAssertionError( - 'getMessages', - '!messages.messagesNotModified', - res._, - ) + throw new MtTypeAssertionError('getMessages', '!messages.messagesNotModified', res._) } const peers = PeersIndex.from(res) diff --git a/packages/client/src/methods/messages/parse-entities.ts b/packages/client/src/methods/messages/parse-entities.ts index c7bbe232..e493ebc0 100644 --- a/packages/client/src/methods/messages/parse-entities.ts +++ b/packages/client/src/methods/messages/parse-entities.ts @@ -44,14 +44,10 @@ export async function _parseEntities( for (const ent of entities) { if (ent._ === 'messageEntityMentionName') { try { - const inputPeer = normalizeToInputUser( - await this.resolvePeer(ent.userId), - ent.userId, - ) + const inputPeer = normalizeToInputUser(await this.resolvePeer(ent.userId), ent.userId) // not a user if (!inputPeer) continue - (ent as any)._ = 'inputMessageEntityMentionName' ;(ent as any).userId = inputPeer } catch (e) {} diff --git a/packages/client/src/methods/messages/read-history.ts b/packages/client/src/methods/messages/read-history.ts index dae25cf3..e187e1df 100644 --- a/packages/client/src/methods/messages/read-history.ts +++ b/packages/client/src/methods/messages/read-history.ts @@ -1,9 +1,6 @@ import { TelegramClient } from '../../client' import { InputPeerLike } from '../../types' -import { - isInputPeerChannel, - normalizeToInputChannel, -} from '../../utils/peer-utils' +import { isInputPeerChannel, normalizeToInputChannel } from '../../utils/peer-utils' import { createDummyUpdate } from '../../utils/updates-utils' /** @@ -29,9 +26,7 @@ export async function readHistory( }) if (isInputPeerChannel(peer)) { - this._handleUpdate( - createDummyUpdate(res.pts, res.ptsCount, peer.channelId), - ) + this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount, peer.channelId)) } else { this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount)) } diff --git a/packages/client/src/methods/messages/read-reactions.ts b/packages/client/src/methods/messages/read-reactions.ts index db066d9b..dd86347c 100644 --- a/packages/client/src/methods/messages/read-reactions.ts +++ b/packages/client/src/methods/messages/read-reactions.ts @@ -8,10 +8,7 @@ import { createDummyUpdate } from '../../utils/updates-utils' * @param chatId Chat ID * @internal */ -export async function readReactions( - this: TelegramClient, - chatId: InputPeerLike, -): Promise { +export async function readReactions(this: TelegramClient, chatId: InputPeerLike): Promise { const res = await this.call({ _: 'messages.readReactions', peer: await this.resolvePeer(chatId), diff --git a/packages/client/src/methods/messages/search-global.ts b/packages/client/src/methods/messages/search-global.ts index 1e74894d..fac71565 100644 --- a/packages/client/src/methods/messages/search-global.ts +++ b/packages/client/src/methods/messages/search-global.ts @@ -71,24 +71,17 @@ export async function* searchGlobal( }) if (res._ === 'messages.messagesNotModified') { - throw new MtTypeAssertionError( - 'messages.searchGlobal', - '!messages.messagesNotModified', - res._, - ) + throw new MtTypeAssertionError('messages.searchGlobal', '!messages.messagesNotModified', res._) } const peers = PeersIndex.from(res) - const msgs = res.messages - .filter((msg) => msg._ !== 'messageEmpty') - .map((msg) => new Message(this, msg, peers)) + const msgs = res.messages.filter((msg) => msg._ !== 'messageEmpty').map((msg) => new Message(this, msg, peers)) if (!msgs.length) break const last = msgs[msgs.length - 1] - offsetRate = - (res as tl.messages.RawMessagesSlice).nextRate ?? last.raw.date + offsetRate = (res as tl.messages.RawMessagesSlice).nextRate ?? last.raw.date offsetPeer = last.chat.inputPeer offsetId = last.id diff --git a/packages/client/src/methods/messages/search-messages.ts b/packages/client/src/methods/messages/search-messages.ts index 01dfbd06..76ee2129 100644 --- a/packages/client/src/methods/messages/search-messages.ts +++ b/packages/client/src/methods/messages/search-messages.ts @@ -123,9 +123,7 @@ export async function* searchMessages( const limit = Math.min(params.chunkSize || 100, total) const peer = await this.resolvePeer(chatId) - const fromUser = - (params.fromUser ? await this.resolvePeer(params.fromUser) : null) || - undefined + const fromUser = (params.fromUser ? await this.resolvePeer(params.fromUser) : null) || undefined for (;;) { const res = await this.call({ @@ -145,11 +143,7 @@ export async function* searchMessages( }) if (res._ === 'messages.messagesNotModified') { - throw new MtTypeAssertionError( - 'messages.search', - '!messages.messagesNotModified', - res._, - ) + throw new MtTypeAssertionError('messages.search', '!messages.messagesNotModified', res._) } // for successive chunks, we need to reset the offset @@ -157,9 +151,7 @@ export async function* searchMessages( const peers = PeersIndex.from(res) - const msgs = res.messages - .filter((msg) => msg._ !== 'messageEmpty') - .map((msg) => new Message(this, msg, peers)) + const msgs = res.messages.filter((msg) => msg._ !== 'messageEmpty').map((msg) => new Message(this, msg, peers)) if (!msgs.length) break diff --git a/packages/client/src/methods/messages/send-copy.ts b/packages/client/src/methods/messages/send-copy.ts index 53f1a336..b1d5603b 100644 --- a/packages/client/src/methods/messages/send-copy.ts +++ b/packages/client/src/methods/messages/send-copy.ts @@ -2,13 +2,7 @@ import { getMarkedPeerId } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - FormattedString, - InputPeerLike, - Message, - MtMessageNotFoundError, - ReplyMarkup, -} from '../../types' +import { FormattedString, InputPeerLike, Message, MtMessageNotFoundError, ReplyMarkup } from '../../types' /** * Copy a message (i.e. send the same message, @@ -107,11 +101,7 @@ export async function sendCopy( const msg = await this.getMessages(fromPeer, message) if (!msg) { - throw new MtMessageNotFoundError( - getMarkedPeerId(fromPeer), - message, - 'to copy', - ) + throw new MtMessageNotFoundError(getMarkedPeerId(fromPeer), message, 'to copy') } return msg.sendCopy(toChatId, params) diff --git a/packages/client/src/methods/messages/send-media-group.ts b/packages/client/src/methods/messages/send-media-group.ts index a1a8054f..8415cbfa 100644 --- a/packages/client/src/methods/messages/send-media-group.ts +++ b/packages/client/src/methods/messages/send-media-group.ts @@ -3,13 +3,7 @@ import { randomLong } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - InputMediaLike, - InputPeerLike, - Message, - MtMessageNotFoundError, - PeersIndex, -} from '../../types' +import { InputMediaLike, InputPeerLike, Message, MtMessageNotFoundError, PeersIndex } from '../../types' import { normalizeDate, normalizeMessageId } from '../../utils/misc-utils' import { assertIsUpdatesGroup } from '../../utils/updates-utils' @@ -86,11 +80,7 @@ export async function sendMediaGroup( * @param uploaded Number of bytes already uploaded * @param total Total file size */ - progressCallback?: ( - index: number, - uploaded: number, - total: number - ) => void + progressCallback?: (index: number, uploaded: number, total: number) => void /** * Whether to clear draft after sending this message. @@ -120,27 +110,18 @@ export async function sendMediaGroup( let replyTo = normalizeMessageId(params.replyTo) if (params.commentTo) { - [peer, replyTo] = await this._getDiscussionMessage( - peer, - normalizeMessageId(params.commentTo)!, - ) + [peer, replyTo] = await this._getDiscussionMessage(peer, normalizeMessageId(params.commentTo)!) } if (params.mustReply) { if (!replyTo) { - throw new MtArgumentError( - 'mustReply used, but replyTo was not passed', - ) + throw new MtArgumentError('mustReply used, but replyTo was not passed') } const msg = await this.getMessages(peer, replyTo) if (!msg) { - throw new MtMessageNotFoundError( - getMarkedPeerId(peer), - replyTo, - 'to reply to', - ) + throw new MtMessageNotFoundError(getMarkedPeerId(peer), replyTo, 'to reply to') } } @@ -200,9 +181,7 @@ export async function sendMediaGroup( scheduleDate: normalizeDate(params.schedule), clearDraft: params.clearDraft, noforwards: params.forbidForwards, - sendAs: params.sendAs ? - await this.resolvePeer(params.sendAs) : - undefined, + sendAs: params.sendAs ? await this.resolvePeer(params.sendAs) : undefined, }) assertIsUpdatesGroup('_findMessageInUpdate', res) @@ -212,25 +191,10 @@ export async function sendMediaGroup( const msgs = res.updates .filter( - ( - u, - ): u is - | tl.RawUpdateNewMessage - | tl.RawUpdateNewChannelMessage - | tl.RawUpdateNewScheduledMessage => - u._ === 'updateNewMessage' || - u._ === 'updateNewChannelMessage' || - u._ === 'updateNewScheduledMessage', - ) - .map( - (u) => - new Message( - this, - u.message, - peers, - u._ === 'updateNewScheduledMessage', - ), + (u): u is tl.RawUpdateNewMessage | tl.RawUpdateNewChannelMessage | tl.RawUpdateNewScheduledMessage => + u._ === 'updateNewMessage' || u._ === 'updateNewChannelMessage' || u._ === 'updateNewScheduledMessage', ) + .map((u) => new Message(this, u.message, peers, u._ === 'updateNewScheduledMessage')) this._pushConversationMessage(msgs[msgs.length - 1]) diff --git a/packages/client/src/methods/messages/send-media.ts b/packages/client/src/methods/messages/send-media.ts index d3f05ea3..ee120d16 100644 --- a/packages/client/src/methods/messages/send-media.ts +++ b/packages/client/src/methods/messages/send-media.ts @@ -146,11 +146,9 @@ export async function sendMedia( // some types dont have `caption` field, and ts warns us, // but since it's JS, they'll just be `undefined` and properly // handled by _parseEntities method - params.caption || - (media as Extract).caption, + params.caption || (media as Extract).caption, params.parseMode, - params.entities || - (media as Extract).entities, + params.entities || (media as Extract).entities, ) let peer = await this.resolvePeer(chatId) @@ -159,27 +157,18 @@ export async function sendMedia( let replyTo = normalizeMessageId(params.replyTo) if (params.commentTo) { - [peer, replyTo] = await this._getDiscussionMessage( - peer, - normalizeMessageId(params.commentTo)!, - ) + [peer, replyTo] = await this._getDiscussionMessage(peer, normalizeMessageId(params.commentTo)!) } if (params.mustReply) { if (!replyTo) { - throw new MtArgumentError( - 'mustReply used, but replyTo was not passed', - ) + throw new MtArgumentError('mustReply used, but replyTo was not passed') } const msg = await this.getMessages(peer, replyTo) if (!msg) { - throw new MtMessageNotFoundError( - getMarkedPeerId(peer), - replyTo, - 'to reply to', - ) + throw new MtMessageNotFoundError(getMarkedPeerId(peer), replyTo, 'to reply to') } } @@ -201,9 +190,7 @@ export async function sendMedia( entities, clearDraft: params.clearDraft, noforwards: params.forbidForwards, - sendAs: params.sendAs ? - await this.resolvePeer(params.sendAs) : - undefined, + sendAs: params.sendAs ? await this.resolvePeer(params.sendAs) : undefined, }) const msg = this._findMessageInUpdate(res) diff --git a/packages/client/src/methods/messages/send-reaction.ts b/packages/client/src/methods/messages/send-reaction.ts index 0963bf2e..3887c71f 100644 --- a/packages/client/src/methods/messages/send-reaction.ts +++ b/packages/client/src/methods/messages/send-reaction.ts @@ -60,16 +60,12 @@ export async function sendReaction( this._handleUpdate(res, true) - const upd = res.updates.find( - (it) => it._ === 'updateEditChannelMessage', - ) as tl.RawUpdateEditChannelMessage | undefined + const upd = res.updates.find((it) => it._ === 'updateEditChannelMessage') as + | tl.RawUpdateEditChannelMessage + | undefined if (!upd) { - throw new MtTypeAssertionError( - 'messages.sendReaction (@ .updates[*])', - 'updateEditChannelMessage', - 'undefined', - ) + throw new MtTypeAssertionError('messages.sendReaction (@ .updates[*])', 'updateEditChannelMessage', 'undefined') } const peers = PeersIndex.from(res) diff --git a/packages/client/src/methods/messages/send-scheduled.ts b/packages/client/src/methods/messages/send-scheduled.ts index 65966d40..fbc0c0d9 100644 --- a/packages/client/src/methods/messages/send-scheduled.ts +++ b/packages/client/src/methods/messages/send-scheduled.ts @@ -15,11 +15,7 @@ import { assertIsUpdatesGroup } from '../../utils/updates-utils' * @param id ID of the message * @internal */ -export async function sendScheduled( - this: TelegramClient, - peer: InputPeerLike, - id: number -): Promise +export async function sendScheduled(this: TelegramClient, peer: InputPeerLike, id: number): Promise /** * Send previously scheduled message(s) @@ -32,11 +28,7 @@ export async function sendScheduled( * @param ids ID(s) of the messages * @internal */ -export async function sendScheduled( - this: TelegramClient, - peer: InputPeerLike, - ids: number[] -): Promise +export async function sendScheduled(this: TelegramClient, peer: InputPeerLike, ids: number[]): Promise /** @internal */ export async function sendScheduled( diff --git a/packages/client/src/methods/messages/send-text.ts b/packages/client/src/methods/messages/send-text.ts index c1a8b717..e48c3993 100644 --- a/packages/client/src/methods/messages/send-text.ts +++ b/packages/client/src/methods/messages/send-text.ts @@ -1,8 +1,4 @@ -import { - getMarkedPeerId, - MtArgumentError, - MtTypeAssertionError, -} from '@mtcute/core' +import { getMarkedPeerId, MtArgumentError, MtTypeAssertionError } from '@mtcute/core' import { randomLong } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' @@ -122,11 +118,7 @@ export async function sendText( ): Promise { if (!params) params = {} - const [message, entities] = await this._parseEntities( - text, - params.parseMode, - params.entities, - ) + const [message, entities] = await this._parseEntities(text, params.parseMode, params.entities) let peer = await this.resolvePeer(chatId) const replyMarkup = BotKeyboard._convertToTl(params.replyMarkup) @@ -134,27 +126,18 @@ export async function sendText( let replyTo = normalizeMessageId(params.replyTo) if (params.commentTo) { - [peer, replyTo] = await this._getDiscussionMessage( - peer, - normalizeMessageId(params.commentTo)!, - ) + [peer, replyTo] = await this._getDiscussionMessage(peer, normalizeMessageId(params.commentTo)!) } if (params.mustReply) { if (!replyTo) { - throw new MtArgumentError( - 'mustReply used, but replyTo was not passed', - ) + throw new MtArgumentError('mustReply used, but replyTo was not passed') } const msg = await this.getMessages(peer, replyTo) if (!msg) { - throw new MtMessageNotFoundError( - getMarkedPeerId(peer), - replyTo, - 'to reply to', - ) + throw new MtMessageNotFoundError(getMarkedPeerId(peer), replyTo, 'to reply to') } } @@ -176,9 +159,7 @@ export async function sendText( entities, clearDraft: params.clearDraft, noforwards: params.forbidForwards, - sendAs: params.sendAs ? - await this.resolvePeer(params.sendAs) : - undefined, + sendAs: params.sendAs ? await this.resolvePeer(params.sendAs) : undefined, }) if (res._ === 'updateShortSentMessage') { @@ -199,9 +180,7 @@ export async function sendText( const peers = new PeersIndex() - const fetchPeer = async ( - peer: tl.TypePeer | tl.TypeInputPeer, - ): Promise => { + const fetchPeer = async (peer: tl.TypePeer | tl.TypeInputPeer): Promise => { const id = getMarkedPeerId(peer) let cached = await this.storage.getFullPeerById(id) @@ -224,11 +203,7 @@ export async function sendText( } if (!cached) { - throw new MtTypeAssertionError( - 'sendText (@ getFullPeerById)', - 'user | chat', - 'null', - ) + throw new MtTypeAssertionError('sendText (@ getFullPeerById)', 'user | chat', 'null') } switch (cached._) { diff --git a/packages/client/src/methods/messages/send-vote.ts b/packages/client/src/methods/messages/send-vote.ts index 629ce691..dffbc0a1 100644 --- a/packages/client/src/methods/messages/send-vote.ts +++ b/packages/client/src/methods/messages/send-vote.ts @@ -1,18 +1,8 @@ -import { - getMarkedPeerId, - MaybeArray, - MtArgumentError, - MtTypeAssertionError, -} from '@mtcute/core' +import { getMarkedPeerId, MaybeArray, MtArgumentError, MtTypeAssertionError } from '@mtcute/core' import { assertTypeIs } from '@mtcute/core/utils' import { TelegramClient } from '../../client' -import { - InputPeerLike, - MtMessageNotFoundError, - PeersIndex, - Poll, -} from '../../types' +import { InputPeerLike, MtMessageNotFoundError, PeersIndex, Poll } from '../../types' import { assertIsUpdatesGroup } from '../../utils/updates-utils' /** @@ -44,11 +34,7 @@ export async function sendVote( const msg = await this.getMessages(peer, message) if (!msg) { - throw new MtMessageNotFoundError( - getMarkedPeerId(peer), - message, - 'to vote in', - ) + throw new MtMessageNotFoundError(getMarkedPeerId(peer), message, 'to vote in') } if (!(msg.media instanceof Poll)) { @@ -80,11 +66,7 @@ export async function sendVote( assertTypeIs('messages.sendVote (@ .updates[0])', upd, 'updateMessagePoll') if (!upd.poll) { - throw new MtTypeAssertionError( - 'messages.sendVote (@ .updates[0].poll)', - 'poll', - 'undefined', - ) + throw new MtTypeAssertionError('messages.sendVote (@ .updates[0].poll)', 'poll', 'undefined') } const peers = PeersIndex.from(res) diff --git a/packages/client/src/methods/messages/translate-message.ts b/packages/client/src/methods/messages/translate-message.ts index f3f9e366..5716d873 100644 --- a/packages/client/src/methods/messages/translate-message.ts +++ b/packages/client/src/methods/messages/translate-message.ts @@ -28,10 +28,5 @@ export async function translateMessage( toLang: toLanguage, }) - return [ - res.result[0].text, - res.result[0].entities - .map((it) => MessageEntity._parse(it)) - .filter(isPresent), - ] + return [res.result[0].text, res.result[0].entities.map((it) => MessageEntity._parse(it)).filter(isPresent)] } diff --git a/packages/client/src/methods/messages/translate-text.ts b/packages/client/src/methods/messages/translate-text.ts index 588aa332..7cce463d 100644 --- a/packages/client/src/methods/messages/translate-text.ts +++ b/packages/client/src/methods/messages/translate-text.ts @@ -11,11 +11,7 @@ import { TelegramClient } from '../../client' * @param toLanguage Target language (two-letter ISO 639-1 language code) * @internal */ -export async function translateText( - this: TelegramClient, - text: string, - toLanguage: string, -): Promise { +export async function translateText(this: TelegramClient, text: string, toLanguage: string): Promise { const res = await this.call({ _: 'messages.translateText', text: [ diff --git a/packages/client/src/methods/messages/unpin-all-messages.ts b/packages/client/src/methods/messages/unpin-all-messages.ts index da6f5aa0..e1a1a13e 100644 --- a/packages/client/src/methods/messages/unpin-all-messages.ts +++ b/packages/client/src/methods/messages/unpin-all-messages.ts @@ -9,10 +9,7 @@ import { createDummyUpdate } from '../../utils/updates-utils' * @param chatId Chat or user ID * @internal */ -export async function unpinAllMessages( - this: TelegramClient, - chatId: InputPeerLike, -): Promise { +export async function unpinAllMessages(this: TelegramClient, chatId: InputPeerLike): Promise { const peer = await this.resolvePeer(chatId) const res = await this.call({ @@ -21,9 +18,7 @@ export async function unpinAllMessages( }) if (isInputPeerChannel(peer)) { - this._handleUpdate( - createDummyUpdate(res.pts, res.ptsCount, peer.channelId), - ) + this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount, peer.channelId)) } else { this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount)) } diff --git a/packages/client/src/methods/messages/unpin-message.ts b/packages/client/src/methods/messages/unpin-message.ts index babfd2f8..8a722b93 100644 --- a/packages/client/src/methods/messages/unpin-message.ts +++ b/packages/client/src/methods/messages/unpin-message.ts @@ -11,11 +11,7 @@ import { InputPeerLike } from '../../types' * @param messageId Message ID * @internal */ -export async function unpinMessage( - this: TelegramClient, - chatId: InputPeerLike, - messageId: number, -): Promise { +export async function unpinMessage(this: TelegramClient, chatId: InputPeerLike, messageId: number): Promise { const res = await this.call({ _: 'messages.updatePinnedMessage', peer: await this.resolvePeer(chatId), diff --git a/packages/client/src/methods/parse-modes/parse-modes.ts b/packages/client/src/methods/parse-modes/parse-modes.ts index ab95118a..1e72de90 100644 --- a/packages/client/src/methods/parse-modes/parse-modes.ts +++ b/packages/client/src/methods/parse-modes/parse-modes.ts @@ -12,16 +12,11 @@ import { IMessageEntityParser } from '../../types' * @throws MtClientError When the parse mode with a given name is already registered. * @internal */ -export function registerParseMode( - this: TelegramClient, - parseMode: IMessageEntityParser, -): void { +export function registerParseMode(this: TelegramClient, parseMode: IMessageEntityParser): void { const name = parseMode.name if (this._parseModes.has(name)) { - throw new MtArgumentError( - `Parse mode ${name} is already registered. Unregister it first!`, - ) + throw new MtArgumentError(`Parse mode ${name} is already registered. Unregister it first!`) } this._parseModes.set(name, parseMode) @@ -56,10 +51,7 @@ export function unregisterParseMode(this: TelegramClient, name: string): void { * @throws MtClientError When `name` is omitted and there is no default parse mode * @internal */ -export function getParseMode( - this: TelegramClient, - name?: string | null, -): IMessageEntityParser { +export function getParseMode(this: TelegramClient, name?: string | null): IMessageEntityParser { if (!name) { if (!this._defaultParseMode) { throw new MtArgumentError('There is no default parse mode') diff --git a/packages/client/src/methods/pasword/change-cloud-password.ts b/packages/client/src/methods/pasword/change-cloud-password.ts index c665c626..ed1da652 100644 --- a/packages/client/src/methods/pasword/change-cloud-password.ts +++ b/packages/client/src/methods/pasword/change-cloud-password.ts @@ -1,9 +1,5 @@ import { MtArgumentError } from '@mtcute/core' -import { - assertTypeIs, - computeNewPasswordHash, - computeSrpParams, -} from '@mtcute/core/utils' +import { assertTypeIs, computeNewPasswordHash, computeSrpParams } from '@mtcute/core/utils' import { TelegramClient } from '../../client' @@ -28,18 +24,10 @@ export async function changeCloudPassword( } const algo = pwd.newAlgo - assertTypeIs( - 'account.getPassword', - algo, - 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow', - ) + assertTypeIs('account.getPassword', algo, 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow') const oldSrp = await computeSrpParams(this._crypto, pwd, currentPassword) - const newHash = await computeNewPasswordHash( - this._crypto, - algo, - newPassword, - ) + const newHash = await computeNewPasswordHash(this._crypto, algo, newPassword) await this.call({ _: 'account.updatePasswordSettings', diff --git a/packages/client/src/methods/pasword/enable-cloud-password.ts b/packages/client/src/methods/pasword/enable-cloud-password.ts index 1c34bcde..8960ccc1 100644 --- a/packages/client/src/methods/pasword/enable-cloud-password.ts +++ b/packages/client/src/methods/pasword/enable-cloud-password.ts @@ -29,11 +29,7 @@ export async function enableCloudPassword( } const algo = pwd.newAlgo - assertTypeIs( - 'account.getPassword', - algo, - 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow', - ) + assertTypeIs('account.getPassword', algo, 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow') const newHash = await computeNewPasswordHash(this._crypto, algo, password) diff --git a/packages/client/src/methods/pasword/password-email.ts b/packages/client/src/methods/pasword/password-email.ts index 7caef3e8..5b128de2 100644 --- a/packages/client/src/methods/pasword/password-email.ts +++ b/packages/client/src/methods/pasword/password-email.ts @@ -6,10 +6,7 @@ import { TelegramClient } from '../../client' * @param code Code which was sent via email * @internal */ -export async function verifyPasswordEmail( - this: TelegramClient, - code: string, -): Promise { +export async function verifyPasswordEmail(this: TelegramClient, code: string): Promise { await this.call({ _: 'account.confirmPasswordEmail', code, diff --git a/packages/client/src/methods/pasword/remove-cloud-password.ts b/packages/client/src/methods/pasword/remove-cloud-password.ts index 843c1791..aa3b5464 100644 --- a/packages/client/src/methods/pasword/remove-cloud-password.ts +++ b/packages/client/src/methods/pasword/remove-cloud-password.ts @@ -9,10 +9,7 @@ import { TelegramClient } from '../../client' * @param password 2FA password as plaintext * @internal */ -export async function removeCloudPassword( - this: TelegramClient, - password: string, -): Promise { +export async function removeCloudPassword(this: TelegramClient, password: string): Promise { const pwd = await this.call({ _: 'account.getPassword' }) if (!pwd.hasPassword) { diff --git a/packages/client/src/methods/stickers/add-sticker-to-set.ts b/packages/client/src/methods/stickers/add-sticker-to-set.ts index 87ea81c8..b7561aab 100644 --- a/packages/client/src/methods/stickers/add-sticker-to-set.ts +++ b/packages/client/src/methods/stickers/add-sticker-to-set.ts @@ -48,10 +48,7 @@ export async function addStickerToSet( stickerset: id, sticker: { _: 'inputStickerSetItem', - document: await this._normalizeFileToDocument( - sticker.file, - params ?? {}, - ), + document: await this._normalizeFileToDocument(sticker.file, params ?? {}), emoji: sticker.emojis, maskCoords: sticker.maskPosition ? { diff --git a/packages/client/src/methods/stickers/create-sticker-set.ts b/packages/client/src/methods/stickers/create-sticker-set.ts index f116fd26..b654ab97 100644 --- a/packages/client/src/methods/stickers/create-sticker-set.ts +++ b/packages/client/src/methods/stickers/create-sticker-set.ts @@ -93,23 +93,14 @@ export async function createStickerSet( * @param uploaded Number of bytes uploaded * @param total Total file size */ - progressCallback?: ( - idx: number, - uploaded: number, - total: number - ) => void + progressCallback?: (idx: number, uploaded: number, total: number) => void }, ): Promise { if (params.type === 'emoji') { - throw new MtArgumentError( - 'Creating emoji stickers is not supported yet by the API', - ) + throw new MtArgumentError('Creating emoji stickers is not supported yet by the API') } - const owner = normalizeToInputUser( - await this.resolvePeer(params.owner), - params.owner, - ) + const owner = normalizeToInputUser(await this.resolvePeer(params.owner), params.owner) const inputStickers: tl.TypeInputStickerSetItem[] = [] @@ -149,9 +140,7 @@ export async function createStickerSet( title: params.title, shortName: params.shortName, stickers: inputStickers, - thumb: params.thumb ? - await this._normalizeFileToDocument(params.thumb, {}) : - undefined, + thumb: params.thumb ? await this._normalizeFileToDocument(params.thumb, {}) : undefined, }) return new StickerSet(this, res) diff --git a/packages/client/src/methods/stickers/get-custom-emojis.ts b/packages/client/src/methods/stickers/get-custom-emojis.ts index 49100fbc..2d6bb84c 100644 --- a/packages/client/src/methods/stickers/get-custom-emojis.ts +++ b/packages/client/src/methods/stickers/get-custom-emojis.ts @@ -12,10 +12,7 @@ import { parseDocument } from '../../types/media/document-utils' * @param ids IDs of the stickers (as defined in {@link MessageEntity.emojiId}) * @internal */ -export async function getCustomEmojis( - this: TelegramClient, - ids: tl.Long[], -): Promise { +export async function getCustomEmojis(this: TelegramClient, ids: tl.Long[]): Promise { const res = await this.call({ _: 'messages.getCustomEmojiDocuments', documentId: ids, @@ -27,11 +24,7 @@ export async function getCustomEmojis( const doc = parseDocument(this, it) if (doc.type !== 'sticker') { - throw new MtTypeAssertionError( - 'getCustomEmojis', - 'sticker', - doc.type, - ) + throw new MtTypeAssertionError('getCustomEmojis', 'sticker', doc.type) } return doc diff --git a/packages/client/src/methods/stickers/get-installed-stickers.ts b/packages/client/src/methods/stickers/get-installed-stickers.ts index d47c8f25..68601a70 100644 --- a/packages/client/src/methods/stickers/get-installed-stickers.ts +++ b/packages/client/src/methods/stickers/get-installed-stickers.ts @@ -15,9 +15,7 @@ import { StickerSet } from '../../types' * * @internal */ -export async function getInstalledStickers( - this: TelegramClient, -): Promise { +export async function getInstalledStickers(this: TelegramClient): Promise { const res = await this.call({ _: 'messages.getAllStickers', hash: Long.ZERO, diff --git a/packages/client/src/methods/updates.ts b/packages/client/src/methods/updates.ts index f606213e..a1cfbc4b 100644 --- a/packages/client/src/methods/updates.ts +++ b/packages/client/src/methods/updates.ts @@ -90,21 +90,11 @@ function _initializeUpdates(this: TelegramClient) { this._updatesLoopActive = false this._updatesLoopCv = new ConditionVariable() - this._pendingUpdateContainers = new SortedLinkedList( - (a, b) => a.seqStart - b.seqStart, - ) - this._pendingPtsUpdates = new SortedLinkedList( - (a, b) => a.ptsBefore! - b.ptsBefore!, - ) - this._pendingPtsUpdatesPostponed = new SortedLinkedList( - (a, b) => a.ptsBefore! - b.ptsBefore!, - ) - this._pendingQtsUpdates = new SortedLinkedList( - (a, b) => a.qtsBefore! - b.qtsBefore!, - ) - this._pendingQtsUpdatesPostponed = new SortedLinkedList( - (a, b) => a.qtsBefore! - b.qtsBefore!, - ) + this._pendingUpdateContainers = new SortedLinkedList((a, b) => a.seqStart - b.seqStart) + this._pendingPtsUpdates = new SortedLinkedList((a, b) => a.ptsBefore! - b.ptsBefore!) + this._pendingPtsUpdatesPostponed = new SortedLinkedList((a, b) => a.ptsBefore! - b.ptsBefore!) + this._pendingQtsUpdates = new SortedLinkedList((a, b) => a.qtsBefore! - b.qtsBefore!) + this._pendingQtsUpdatesPostponed = new SortedLinkedList((a, b) => a.qtsBefore! - b.qtsBefore!) this._pendingUnorderedUpdates = new Deque() this._updLock = new AsyncLock() @@ -133,11 +123,7 @@ function _initializeUpdates(this: TelegramClient) { * @param time Window time * @internal */ -export function enableRps( - this: TelegramClient, - size?: number, - time?: number, -): void { +export function enableRps(this: TelegramClient, size?: number, time?: number): void { this._rpsIncoming = new RpsMeter(size, time) this._rpsProcessing = new RpsMeter(size, time) } @@ -155,9 +141,7 @@ export function enableRps( */ export function getCurrentRpsIncoming(this: TelegramClient): number { if (!this._rpsIncoming) { - throw new MtArgumentError( - 'RPS meter is not enabled, use .enableRps() first', - ) + throw new MtArgumentError('RPS meter is not enabled, use .enableRps() first') } return this._rpsIncoming.getRps() @@ -176,9 +160,7 @@ export function getCurrentRpsIncoming(this: TelegramClient): number { */ export function getCurrentRpsProcessing(this: TelegramClient): number { if (!this._rpsProcessing) { - throw new MtArgumentError( - 'RPS meter is not enabled, use .enableRps() first', - ) + throw new MtArgumentError('RPS meter is not enabled, use .enableRps() first') } return this._rpsProcessing.getRps() @@ -319,10 +301,7 @@ export function _onStop(this: TelegramClient): void { /** * @internal */ -export async function _saveStorage( - this: TelegramClient, - afterImport = false, -): Promise { +export async function _saveStorage(this: TelegramClient, afterImport = false): Promise { // save updates state to the session if (afterImport) { @@ -378,11 +357,7 @@ export async function _saveStorage( /** * @internal */ -export function _dispatchUpdate( - this: TelegramClient, - update: tl.TypeUpdate | tl.TypeMessage, - peers: PeersIndex, -): void { +export function _dispatchUpdate(this: TelegramClient, update: tl.TypeUpdate | tl.TypeMessage, peers: PeersIndex): void { this.emit('raw_update', update, peers) const parsed = _parseUpdate(this, update, peers) @@ -469,10 +444,7 @@ export function _dispatchUpdate( // return ret // } -async function _replaceMinPeers( - this: TelegramClient, - peers: PeersIndex, -): Promise { +async function _replaceMinPeers(this: TelegramClient, peers: PeersIndex): Promise { for (const [key, user_] of peers.users) { const user = user_ as Exclude @@ -517,10 +489,7 @@ async function _fetchPeersForShort( const fetchPeer = async (peer?: tl.TypePeer | number) => { if (!peer) return true - const bare = - typeof peer === 'number' ? - markedPeerIdToBare(peer) : - getBarePeerId(peer) + const bare = typeof peer === 'number' ? markedPeerIdToBare(peer) : getBarePeerId(peer) const marked = typeof peer === 'number' ? peer : getMarkedPeerId(peer) @@ -544,10 +513,7 @@ async function _fetchPeersForShort( case 'updateNewChannelMessage': case 'updateEditMessage': case 'updateEditChannelMessage': { - const msg = - upd._ === 'message' || upd._ === 'messageService' ? - upd : - upd.message + const msg = upd._ === 'message' || upd._ === 'messageService' ? upd : upd.message if (msg._ === 'messageEmpty') return null // ref: https://github.com/tdlib/td/blob/master/td/telegram/UpdatesManager.cpp @@ -556,16 +522,10 @@ async function _fetchPeersForShort( if (!(await fetchPeer(msg.fromId))) return null if (msg.replyTo) { - if ( - msg.replyTo._ === 'messageReplyHeader' && - !(await fetchPeer(msg.replyTo.replyToPeerId)) - ) { + if (msg.replyTo._ === 'messageReplyHeader' && !(await fetchPeer(msg.replyTo.replyToPeerId))) { return null } - if ( - msg.replyTo._ === 'messageReplyStoryHeader' && - !(await fetchPeer(msg.replyTo.userId)) - ) { + if (msg.replyTo._ === 'messageReplyStoryHeader' && !(await fetchPeer(msg.replyTo.userId))) { return null } } @@ -573,8 +533,7 @@ async function _fetchPeersForShort( if (msg._ !== 'messageService') { if ( msg.fwdFrom && - (!(await fetchPeer(msg.fwdFrom.fromId)) || - !(await fetchPeer(msg.fwdFrom.savedFromPeer))) + (!(await fetchPeer(msg.fwdFrom.fromId)) || !(await fetchPeer(msg.fwdFrom.savedFromPeer))) ) { return null } @@ -591,10 +550,7 @@ async function _fetchPeersForShort( if (msg.media) { switch (msg.media._) { case 'messageMediaContact': - if ( - msg.media.userId && - !(await fetchPeer(msg.media.userId)) - ) { + if (msg.media.userId && !(await fetchPeer(msg.media.userId))) { return null } } @@ -617,11 +573,7 @@ async function _fetchPeersForShort( if (!(await fetchPeer(msg.action.userId))) return null break case 'messageActionChatMigrateTo': - if ( - !(await fetchPeer( - toggleChannelIdMark(msg.action.channelId), - )) - ) { + if (!(await fetchPeer(toggleChannelIdMark(msg.action.channelId)))) { return null } break @@ -650,10 +602,7 @@ async function _fetchPeersForShort( } function _isMessageEmpty(upd: tl.TypeUpdate): boolean { - return ( - (upd as Extract).message?._ === - 'messageEmpty' - ) + return (upd as Extract).message?._ === 'messageEmpty' } /** @@ -688,10 +637,7 @@ export function _handleUpdate( case 'updatesCombined': this._pendingUpdateContainers.add({ upd: update, - seqStart: - update._ === 'updatesCombined' ? - update.seqStart : - update.seq, + seqStart: update._ === 'updatesCombined' ? update.seqStart : update.seq, seqEnd: update.seq, }) break @@ -724,10 +670,7 @@ export function catchUp(this: TelegramClient): void { // .then(() => this._saveStorage()) } -function _toPendingUpdate( - upd: tl.TypeUpdate, - peers?: PeersIndex, -): PendingUpdate { +function _toPendingUpdate(upd: tl.TypeUpdate, peers?: PeersIndex): PendingUpdate { const channelId = extractChannelIdFromUpdate(upd) || 0 const pts = 'pts' in upd ? upd.pts : undefined // eslint-disable-next-line no-nested-ternary @@ -797,10 +740,7 @@ async function _fetchChannelDifference( if (!_pts) _pts = fallbackPts if (!_pts) { - this._updsLog.debug( - 'fetchChannelDifference failed for channel %d: base pts not available', - channelId, - ) + this._updsLog.debug('fetchChannelDifference failed for channel %d: base pts not available', channelId) return } @@ -808,14 +748,9 @@ async function _fetchChannelDifference( let channel try { - channel = normalizeToInputChannel( - await this.resolvePeer(toggleChannelIdMark(channelId)), - ) + channel = normalizeToInputChannel(await this.resolvePeer(toggleChannelIdMark(channelId))) } catch (e) { - this._updsLog.warn( - 'fetchChannelDifference failed for channel %d: input peer not found', - channelId, - ) + this._updsLog.warn('fetchChannelDifference failed for channel %d: input peer not found', channelId) return } @@ -843,10 +778,7 @@ async function _fetchChannelDifference( ) if (diff._ === 'updates.channelDifferenceEmpty') { - this._updsLog.debug( - 'getChannelDifference (cid = %d) returned channelDifferenceEmpty', - channelId, - ) + this._updsLog.debug('getChannelDifference (cid = %d) returned channelDifferenceEmpty', channelId) break } @@ -876,9 +808,7 @@ async function _fetchChannelDifference( if (message._ === 'messageEmpty') return - this._pendingUnorderedUpdates.pushBack( - _toPendingUpdate(_messageToUpdate(message), peers), - ) + this._pendingUnorderedUpdates.pushBack(_toPendingUpdate(_messageToUpdate(message), peers)) }) break } @@ -893,18 +823,11 @@ async function _fetchChannelDifference( ) diff.newMessages.forEach((message) => { - this._updsLog.debug( - 'processing message %d (%s) from diff for channel %d', - message.id, - message._, - channelId, - ) + this._updsLog.debug('processing message %d (%s) from diff for channel %d', message.id, message._, channelId) if (message._ === 'messageEmpty') return - this._pendingUnorderedUpdates.pushBack( - _toPendingUpdate(_messageToUpdate(message), peers), - ) + this._pendingUnorderedUpdates.pushBack(_toPendingUpdate(_messageToUpdate(message), peers)) }) diff.otherUpdates.forEach((upd) => { @@ -945,11 +868,7 @@ function _fetchChannelDifferenceLater( _fetchChannelDifference .call(this, channelId, fallbackPts, force) .catch((err) => { - this._updsLog.warn( - 'error fetching difference for %d: %s', - channelId, - err, - ) + this._updsLog.warn('error fetching difference for %d: %s', channelId, err) }) .then(() => { requestedDiff.delete(channelId) @@ -958,10 +877,7 @@ function _fetchChannelDifferenceLater( } } -async function _fetchDifference( - this: TelegramClient, - requestedDiff: Map>, -): Promise { +async function _fetchDifference(this: TelegramClient, requestedDiff: Map>): Promise { for (;;) { const diff = await this.call({ _: 'updates.getDifference', @@ -972,24 +888,17 @@ async function _fetchDifference( switch (diff._) { case 'updates.differenceEmpty': - this._updsLog.debug( - 'updates.getDifference returned updates.differenceEmpty', - ) + this._updsLog.debug('updates.getDifference returned updates.differenceEmpty') return case 'updates.differenceTooLong': this._pts = diff.pts - this._updsLog.debug( - 'updates.getDifference returned updates.differenceTooLong', - ) + this._updsLog.debug('updates.getDifference returned updates.differenceTooLong') return } - const state = - diff._ === 'updates.difference' ? - diff.state : - diff.intermediateState + const state = diff._ === 'updates.difference' ? diff.state : diff.intermediateState this._updsLog.debug( 'updates.getDifference returned %d messages, %d updates. new pts: %d, qts: %d, seq: %d, final: %b', @@ -1016,9 +925,7 @@ async function _fetchDifference( if (message._ === 'messageEmpty') return // pts does not need to be checked for them - this._pendingUnorderedUpdates.pushBack( - _toPendingUpdate(_messageToUpdate(message), peers), - ) + this._pendingUnorderedUpdates.pushBack(_toPendingUpdate(_messageToUpdate(message), peers)) }) diff.otherUpdates.forEach((upd) => { @@ -1029,12 +936,7 @@ async function _fetchDifference( upd.pts, ) - _fetchChannelDifferenceLater.call( - this, - requestedDiff, - upd.channelId, - upd.pts, - ) + _fetchChannelDifferenceLater.call(this, requestedDiff, upd.channelId, upd.pts) return } @@ -1072,20 +974,14 @@ async function _fetchDifference( } } -function _fetchDifferenceLater( - this: TelegramClient, - requestedDiff: Map>, -): void { +function _fetchDifferenceLater(this: TelegramClient, requestedDiff: Map>): void { if (!requestedDiff.has(0)) { requestedDiff.set( 0, _fetchDifference .call(this, requestedDiff) .catch((err) => { - this._updsLog.warn( - 'error fetching common difference: %s', - err, - ) + this._updsLog.warn('error fetching common difference: %s', err) }) .then(() => { requestedDiff.delete(0) @@ -1115,11 +1011,7 @@ async function _onUpdate( ) if (pending.channelId) { - _fetchChannelDifferenceLater.call( - this, - requestedDiff, - pending.channelId, - ) + _fetchChannelDifferenceLater.call(this, requestedDiff, pending.channelId) } else { _fetchDifferenceLater.call(this, requestedDiff) } @@ -1141,11 +1033,7 @@ async function _onUpdate( ) if (pending.channelId) { - _fetchChannelDifferenceLater.call( - this, - requestedDiff, - pending.channelId, - ) + _fetchChannelDifferenceLater.call(this, requestedDiff, pending.channelId) } else { _fetchDifferenceLater.call(this, requestedDiff) } @@ -1160,9 +1048,7 @@ async function _onUpdate( // because unordered may contain pts/qts values when received from diff if (pending.pts) { - const localPts = pending.channelId ? - this._cpts.get(pending.channelId) : - this._pts + const localPts = pending.channelId ? this._cpts.get(pending.channelId) : this._pts if (localPts && pending.ptsBefore !== localPts) { this._updsLog.warn( @@ -1234,8 +1120,7 @@ async function _onUpdate( break case 'updateUserName': if (upd.userId === this._userId) { - this._selfUsername = - upd.usernames.find((it) => it.active)?.username ?? null + this._selfUsername = upd.usernames.find((it) => it.active)?.username ?? null } break } @@ -1286,14 +1171,11 @@ export async function _updatesLoop(this: TelegramClient): Promise { // first process pending containers while (this._pendingUpdateContainers.length) { - const { upd, seqStart, seqEnd } = - this._pendingUpdateContainers.popFront()! + const { upd, seqStart, seqEnd } = this._pendingUpdateContainers.popFront()! switch (upd._) { case 'updatesTooLong': - log.debug( - 'received updatesTooLong, fetching difference', - ) + log.debug('received updatesTooLong, fetching difference') _fetchDifferenceLater.call(this, requestedDiff) break case 'updatesCombined': @@ -1329,11 +1211,7 @@ export async function _updatesLoop(this: TelegramClient): Promise { _fetchDifferenceLater.call(this, requestedDiff) } } else { - log.debug( - 'received %s (size = %d)', - upd._, - upd.updates.length, - ) + log.debug('received %s (size = %d)', upd._, upd.updates.length) } await this._cachePeersFrom(upd) @@ -1359,12 +1237,7 @@ export async function _updatesLoop(this: TelegramClient): Promise { update.channelId, update.pts, ) - _fetchChannelDifferenceLater.call( - this, - requestedDiff, - update.channelId, - update.pts, - ) + _fetchChannelDifferenceLater.call(this, requestedDiff, update.channelId, update.pts) continue } @@ -1515,9 +1388,7 @@ export async function _updatesLoop(this: TelegramClient): Promise { // update gaps (i.e. first update received is considered // to be the base state) - const saved = await this.storage.getChannelPts( - pending.channelId, - ) + const saved = await this.storage.getChannelPts(pending.channelId) if (saved) { this._cpts.set(pending.channelId, saved) @@ -1561,11 +1432,7 @@ export async function _updatesLoop(this: TelegramClient): Promise { ) if (pending.channelId) { - _fetchChannelDifferenceLater.call( - this, - requestedDiff, - pending.channelId, - ) + _fetchChannelDifferenceLater.call(this, requestedDiff, pending.channelId) } else { _fetchDifferenceLater.call(this, requestedDiff) } @@ -1578,11 +1445,7 @@ export async function _updatesLoop(this: TelegramClient): Promise { } // process postponed pts-ordered updates - for ( - let item = this._pendingPtsUpdatesPostponed._first; - item; - item = item.n - ) { + for (let item = this._pendingPtsUpdatesPostponed._first; item; item = item.n) { // awesome fucking iteration because i'm so fucking tired and wanna kms const pending = item.v const upd = pending.update @@ -1596,11 +1459,7 @@ export async function _updatesLoop(this: TelegramClient): Promise { // channel pts from storage will be available because we loaded it earlier if (!localPts) { - log.warn( - 'local pts not available for postponed %s (cid = %d), skipping', - upd._, - pending.channelId, - ) + log.warn('local pts not available for postponed %s (cid = %d), skipping', upd._, pending.channelId) continue } @@ -1643,11 +1502,7 @@ export async function _updatesLoop(this: TelegramClient): Promise { this._pendingPtsUpdatesPostponed._remove(item) if (pending.channelId) { - _fetchChannelDifferenceLater.call( - this, - requestedDiff, - pending.channelId, - ) + _fetchChannelDifferenceLater.call(this, requestedDiff, pending.channelId) } else { _fetchDifferenceLater.call(this, requestedDiff) } @@ -1706,11 +1561,7 @@ export async function _updatesLoop(this: TelegramClient): Promise { } // process postponed qts-ordered updates - for ( - let item = this._pendingQtsUpdatesPostponed._first; - item; - item = item.n - ) { + for (let item = this._pendingQtsUpdatesPostponed._first; item; item = item.n) { // awesome fucking iteration because i'm so fucking tired and wanna kms const pending = item.v const upd = pending.update diff --git a/packages/client/src/methods/users/block-user.ts b/packages/client/src/methods/users/block-user.ts index 5991f463..e4a3c84b 100644 --- a/packages/client/src/methods/users/block-user.ts +++ b/packages/client/src/methods/users/block-user.ts @@ -7,10 +7,7 @@ import { InputPeerLike } from '../../types' * @param id User ID, username or phone number * @internal */ -export async function blockUser( - this: TelegramClient, - id: InputPeerLike, -): Promise { +export async function blockUser(this: TelegramClient, id: InputPeerLike): Promise { await this.call({ _: 'contacts.block', id: await this.resolvePeer(id), diff --git a/packages/client/src/methods/users/get-common-chats.ts b/packages/client/src/methods/users/get-common-chats.ts index 3e91340f..3da48881 100644 --- a/packages/client/src/methods/users/get-common-chats.ts +++ b/packages/client/src/methods/users/get-common-chats.ts @@ -9,10 +9,7 @@ import { normalizeToInputUser } from '../../utils/peer-utils' * @throws MtInvalidPeerTypeError * @internal */ -export async function getCommonChats( - this: TelegramClient, - userId: InputPeerLike, -): Promise { +export async function getCommonChats(this: TelegramClient, userId: InputPeerLike): Promise { return this.call({ _: 'messages.getCommonChats', userId: normalizeToInputUser(await this.resolvePeer(userId), userId), diff --git a/packages/client/src/methods/users/get-users.ts b/packages/client/src/methods/users/get-users.ts index 60ebf0ba..32c20a33 100644 --- a/packages/client/src/methods/users/get-users.ts +++ b/packages/client/src/methods/users/get-users.ts @@ -10,10 +10,7 @@ import { normalizeToInputUser } from '../../utils/peer-utils' * @param id User's identifier. Can be ID, username, phone number, `"me"` or `"self"` or TL object * @internal */ -export async function getUsers( - this: TelegramClient, - id: InputPeerLike -): Promise +export async function getUsers(this: TelegramClient, id: InputPeerLike): Promise /** * Get information about multiple users. @@ -24,23 +21,14 @@ export async function getUsers( * @param ids Users' identifiers. Can be ID, username, phone number, `"me"`, `"self"` or TL object * @internal */ -export async function getUsers( - this: TelegramClient, - ids: InputPeerLike[] -): Promise +export async function getUsers(this: TelegramClient, ids: InputPeerLike[]): Promise /** @internal */ -export async function getUsers( - this: TelegramClient, - ids: MaybeArray, -): Promise> { +export async function getUsers(this: TelegramClient, ids: MaybeArray): Promise> { const isArray = Array.isArray(ids) if (!isArray) ids = [ids as InputPeerLike] - const inputPeers = await this.resolvePeerMany( - ids as InputPeerLike[], - normalizeToInputUser, - ) + const inputPeers = await this.resolvePeerMany(ids as InputPeerLike[], normalizeToInputUser) let res = await this.call({ _: 'users.getUsers', @@ -49,7 +37,5 @@ export async function getUsers( res = res.filter((it) => it._ !== 'userEmpty') - return isArray ? - res.map((it) => new User(this, it)) : - new User(this, res[0]) + return isArray ? res.map((it) => new User(this, it)) : new User(this, res[0]) } diff --git a/packages/client/src/methods/users/resolve-peer-many.ts b/packages/client/src/methods/users/resolve-peer-many.ts index 9a063182..c535a6a7 100644 --- a/packages/client/src/methods/users/resolve-peer-many.ts +++ b/packages/client/src/methods/users/resolve-peer-many.ts @@ -16,12 +16,10 @@ import { InputPeerLike } from '../../types' * @param normalizer Normalization function * @internal */ -export async function resolvePeerMany< - T extends tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel ->( +export async function resolvePeerMany( this: TelegramClient, peerIds: InputPeerLike[], - normalizer: (obj: tl.TypeInputPeer) => T | null + normalizer: (obj: tl.TypeInputPeer) => T | null, ): Promise /** @@ -32,10 +30,7 @@ export async function resolvePeerMany< * @param peerIds Peer Ids * @internal */ -export async function resolvePeerMany( - this: TelegramClient, - peerIds: InputPeerLike[] -): Promise +export async function resolvePeerMany(this: TelegramClient, peerIds: InputPeerLike[]): Promise /** * @internal @@ -43,12 +38,9 @@ export async function resolvePeerMany( export async function resolvePeerMany( this: TelegramClient, peerIds: InputPeerLike[], - normalizer?: ( - obj: tl.TypeInputPeer - ) => tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel | null, + normalizer?: (obj: tl.TypeInputPeer) => tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel | null, ): Promise<(tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel)[]> { - const ret: (tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel)[] = - [] + const ret: (tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel)[] = [] if (peerIds.length < 10) { // no point in using async pool for <10 peers @@ -64,13 +56,9 @@ export async function resolvePeerMany( } } } else { - for await (const { error, value } of asyncPool( - (it) => this.resolvePeer(it), - peerIds, - { - limit: 10, - }, - )) { + for await (const { error, value } of asyncPool((it) => this.resolvePeer(it), peerIds, { + limit: 10, + })) { if (error) { throw error } diff --git a/packages/client/src/methods/users/resolve-peer.ts b/packages/client/src/methods/users/resolve-peer.ts index 66792929..aaa5b7b1 100644 --- a/packages/client/src/methods/users/resolve-peer.ts +++ b/packages/client/src/methods/users/resolve-peer.ts @@ -1,11 +1,6 @@ import Long from 'long' -import { - getBasicPeerType, - getMarkedPeerId, - MtTypeAssertionError, - toggleChannelIdMark, -} from '@mtcute/core' +import { getBasicPeerType, getMarkedPeerId, MtTypeAssertionError, toggleChannelIdMark } from '@mtcute/core' import { assertTypeIs } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' @@ -57,9 +52,7 @@ export async function resolvePeer( assertTypeIs('contacts.getContacts', res, 'contacts.contacts') - const found = res.users.find( - (it) => (it as tl.RawUser).phone === peerId, - ) + const found = res.users.find((it) => (it as tl.RawUser).phone === peerId) if (found && found._ === 'user') { return { @@ -69,15 +62,11 @@ export async function resolvePeer( } } - throw new MtPeerNotFoundError( - `Could not find a peer by phone ${peerId}`, - ) + throw new MtPeerNotFoundError(`Could not find a peer by phone ${peerId}`) } else { // username if (!force) { - const fromStorage = await this.storage.getPeerByUsername( - peerId.toLowerCase(), - ) + const fromStorage = await this.storage.getPeerByUsername(peerId.toLowerCase()) if (fromStorage) return fromStorage } @@ -112,20 +101,11 @@ export async function resolvePeer( const found = res.chats.find((it) => it.id === id) if (found) { - if ( - !( - found._ === 'channel' || - found._ === 'channelForbidden' - ) - ) { + if (!(found._ === 'channel' || found._ === 'channelForbidden')) { // chats can't have usernames // furthermore, our id is a channel id, so it must be a channel // this should never happen, unless Telegram goes crazy - throw new MtTypeAssertionError( - 'contacts.resolveUsername#chats', - 'channel', - found._, - ) + throw new MtTypeAssertionError('contacts.resolveUsername#chats', 'channel', found._) } if (!found.accessHash) { @@ -143,16 +123,10 @@ export async function resolvePeer( } } else { // chats can't have usernames - throw new MtTypeAssertionError( - 'contacts.resolveUsername', - 'user or channel', - res.peer._, - ) + throw new MtTypeAssertionError('contacts.resolveUsername', 'user or channel', res.peer._) } - throw new MtPeerNotFoundError( - `Could not find a peer by username ${peerId}`, - ) + throw new MtPeerNotFoundError(`Could not find a peer by username ${peerId}`) } } @@ -228,10 +202,7 @@ export async function resolvePeer( const found = res.chats.find((it) => it.id === id) - if ( - found && - (found._ === 'channel' || found._ === 'channelForbidden') - ) { + if (found && (found._ === 'channel' || found._ === 'channelForbidden')) { if (!found.accessHash) { // shouldn't happen? but just in case throw new MtPeerNotFoundError( diff --git a/packages/client/src/methods/users/set-offline.ts b/packages/client/src/methods/users/set-offline.ts index 71694f75..c0836e76 100644 --- a/packages/client/src/methods/users/set-offline.ts +++ b/packages/client/src/methods/users/set-offline.ts @@ -6,10 +6,7 @@ import { TelegramClient } from '../../client' * @param offline Whether the user is currently offline * @internal */ -export async function setOffline( - this: TelegramClient, - offline = true, -): Promise { +export async function setOffline(this: TelegramClient, offline = true): Promise { await this.call({ _: 'account.updateStatus', offline, diff --git a/packages/client/src/methods/users/set-profile-photo.ts b/packages/client/src/methods/users/set-profile-photo.ts index c14e9ca8..11933c5b 100644 --- a/packages/client/src/methods/users/set-profile-photo.ts +++ b/packages/client/src/methods/users/set-profile-photo.ts @@ -24,10 +24,7 @@ export async function setProfilePhoto( previewSec?: number, ): Promise { // try parsing media as file id or input photo - if ( - tdFileId.isFileIdLike(media) || - (typeof media === 'object' && tl.isAnyInputPhoto(media)) - ) { + if (tdFileId.isFileIdLike(media) || (typeof media === 'object' && tl.isAnyInputPhoto(media))) { if (typeof media === 'string' && media.match(/^https?:\/\//)) { throw new MtArgumentError("Profile photo can't be set from URL.") } @@ -48,10 +45,7 @@ export async function setProfilePhoto( const res = await this.call({ _: 'photos.uploadProfilePhoto', - [type === 'photo' ? 'file' : 'video']: await this._normalizeInputFile( - media, - {}, - ), + [type === 'photo' ? 'file' : 'video']: await this._normalizeInputFile(media, {}), videoStartTs: previewSec, }) diff --git a/packages/client/src/methods/users/unblock-user.ts b/packages/client/src/methods/users/unblock-user.ts index 7989c12b..a08d1f86 100644 --- a/packages/client/src/methods/users/unblock-user.ts +++ b/packages/client/src/methods/users/unblock-user.ts @@ -7,10 +7,7 @@ import { InputPeerLike } from '../../types' * @param id User ID, username or phone number * @internal */ -export async function unblockUser( - this: TelegramClient, - id: InputPeerLike, -): Promise { +export async function unblockUser(this: TelegramClient, id: InputPeerLike): Promise { await this.call({ _: 'contacts.unblock', id: await this.resolvePeer(id), diff --git a/packages/client/src/methods/users/update-username.ts b/packages/client/src/methods/users/update-username.ts index 8fe615b1..6202ab4b 100644 --- a/packages/client/src/methods/users/update-username.ts +++ b/packages/client/src/methods/users/update-username.ts @@ -10,10 +10,7 @@ import { User } from '../../types' * @param username New username (5-32 chars, allowed chars: `a-zA-Z0-9_`), or `null` to remove * @internal */ -export async function updateUsername( - this: TelegramClient, - username: string | null, -): Promise { +export async function updateUsername(this: TelegramClient, username: string | null): Promise { if (username === null) username = '' const res = await this.call({ diff --git a/packages/client/src/types/auth/sent-code.ts b/packages/client/src/types/auth/sent-code.ts index e52eb0af..0ef84b28 100644 --- a/packages/client/src/types/auth/sent-code.ts +++ b/packages/client/src/types/auth/sent-code.ts @@ -2,18 +2,17 @@ import { tl } from '@mtcute/tl' import { makeInspectable } from '../utils' -const sentCodeMap: Record = - { - 'auth.sentCodeTypeApp': 'app', - 'auth.sentCodeTypeCall': 'call', - 'auth.sentCodeTypeFlashCall': 'flash_call', - 'auth.sentCodeTypeSms': 'sms', - 'auth.sentCodeTypeMissedCall': 'missed_call', - 'auth.sentCodeTypeEmailCode': 'email', - 'auth.sentCodeTypeSetUpEmailRequired': 'email_required', - 'auth.sentCodeTypeFragmentSms': 'fragment', - 'auth.sentCodeTypeFirebaseSms': 'firebase', - } +const sentCodeMap: Record = { + 'auth.sentCodeTypeApp': 'app', + 'auth.sentCodeTypeCall': 'call', + 'auth.sentCodeTypeFlashCall': 'flash_call', + 'auth.sentCodeTypeSms': 'sms', + 'auth.sentCodeTypeMissedCall': 'missed_call', + 'auth.sentCodeTypeEmailCode': 'email', + 'auth.sentCodeTypeSetUpEmailRequired': 'email_required', + 'auth.sentCodeTypeFragmentSms': 'fragment', + 'auth.sentCodeTypeFirebaseSms': 'firebase', +} const nextCodeMap: Record = { 'auth.codeTypeCall': 'call', diff --git a/packages/client/src/types/bots/callback-query.ts b/packages/client/src/types/bots/callback-query.ts index 6f8cef47..183a0dff 100644 --- a/packages/client/src/types/bots/callback-query.ts +++ b/packages/client/src/types/bots/callback-query.ts @@ -1,9 +1,4 @@ -import { - BasicPeerType, - getBasicPeerType, - getMarkedPeerId, - MtArgumentError, -} from '@mtcute/core' +import { BasicPeerType, getBasicPeerType, getMarkedPeerId, MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' @@ -20,9 +15,7 @@ import { makeInspectable } from '../utils' export class CallbackQuery { constructor( readonly client: TelegramClient, - readonly raw: - | tl.RawUpdateBotCallbackQuery - | tl.RawUpdateInlineBotCallbackQuery, + readonly raw: tl.RawUpdateBotCallbackQuery | tl.RawUpdateInlineBotCallbackQuery, readonly _peers: PeersIndex, ) {} @@ -38,10 +31,7 @@ export class CallbackQuery { * User who has pressed the button */ get user(): User { - return (this._user ??= new User( - this.client, - this._peers.user(this.raw.userId), - )) + return (this._user ??= new User(this.client, this._peers.user(this.raw.userId))) } /** @@ -75,9 +65,7 @@ export class CallbackQuery { */ get inlineMessageId(): tl.TypeInputBotInlineMessageID { if (this.raw._ !== 'updateInlineBotCallbackQuery') { - throw new MtArgumentError( - 'Cannot get inline message id for non-inline callback', - ) + throw new MtArgumentError('Cannot get inline message id for non-inline callback') } return this.raw.msgId @@ -94,9 +82,7 @@ export class CallbackQuery { */ get inlineMessageIdStr(): string { if (this.raw._ !== 'updateInlineBotCallbackQuery') { - throw new MtArgumentError( - 'Cannot get inline message id for non-inline callback', - ) + throw new MtArgumentError('Cannot get inline message id for non-inline callback') } return encodeInlineMessageId(this.raw.msgId) @@ -107,9 +93,7 @@ export class CallbackQuery { */ get chatId(): number { if (this.raw._ !== 'updateBotCallbackQuery') { - throw new MtArgumentError( - 'Cannot get message id for inline callback', - ) + throw new MtArgumentError('Cannot get message id for inline callback') } return getMarkedPeerId(this.raw.peer) @@ -131,9 +115,7 @@ export class CallbackQuery { */ get messageId(): number { if (this.raw._ !== 'updateBotCallbackQuery') { - throw new MtArgumentError( - 'Cannot get message id for inline callback', - ) + throw new MtArgumentError('Cannot get message id for inline callback') } return this.raw.msgId @@ -182,19 +164,13 @@ export class CallbackQuery { */ async getMessage(): Promise { if (this.raw._ !== 'updateBotCallbackQuery') { - throw new MtArgumentError( - 'Cannot get a message for inline callback', - ) + throw new MtArgumentError('Cannot get a message for inline callback') } const msg = await this.client.getMessages(this.raw.peer, this.raw.msgId) if (!msg) { - throw new MtMessageNotFoundError( - getMarkedPeerId(this.raw.peer), - this.raw.msgId, - 'with button', - ) + throw new MtMessageNotFoundError(getMarkedPeerId(this.raw.peer), this.raw.msgId, 'with button') } return msg @@ -203,28 +179,20 @@ export class CallbackQuery { /** * Answer this query */ - async answer( - params?: Parameters[1], - ): Promise { + async answer(params?: Parameters[1]): Promise { return this.client.answerCallbackQuery(this.raw.queryId, params) } /** * Edit the message that originated this callback query */ - async editMessage( - params: Parameters[1], - ): Promise { + async editMessage(params: Parameters[1]): Promise { // we can use editInlineMessage as a parameter since they share most of the parameters, // except the ones that won't apply to already sent message anyways. if (this.raw._ === 'updateInlineBotCallbackQuery') { return this.client.editInlineMessage(this.raw.msgId, params) } - await this.client.editMessage( - getMarkedPeerId(this.raw.peer), - this.raw.msgId, - params, - ) + await this.client.editMessage(getMarkedPeerId(this.raw.peer), this.raw.msgId, params) } } diff --git a/packages/client/src/types/bots/command-scope.ts b/packages/client/src/types/bots/command-scope.ts index 41df4598..f21ac527 100644 --- a/packages/client/src/types/bots/command-scope.ts +++ b/packages/client/src/types/bots/command-scope.ts @@ -82,10 +82,7 @@ export namespace BotCommands { /** * Scope that covers a specific user in a specific group */ - export function groupMember( - chat: InputPeerLike, - user: InputPeerLike, - ): IntermediateScope { + export function groupMember(chat: InputPeerLike, user: InputPeerLike): IntermediateScope { return { type: 'member', chat, @@ -99,10 +96,7 @@ export namespace BotCommands { * @param command Bot command (without slash) * @param description Command description */ - export function cmd( - command: string, - description: string, - ): tl.RawBotCommand { + export function cmd(command: string, description: string): tl.RawBotCommand { return { _: 'botCommand', command, diff --git a/packages/client/src/types/bots/game-high-score.ts b/packages/client/src/types/bots/game-high-score.ts index cc625d7d..f7dc574b 100644 --- a/packages/client/src/types/bots/game-high-score.ts +++ b/packages/client/src/types/bots/game-high-score.ts @@ -8,21 +8,14 @@ import { makeInspectable } from '../utils' * Game high score */ export class GameHighScore { - constructor( - readonly client: TelegramClient, - readonly raw: tl.RawHighScore, - readonly _peers: PeersIndex, - ) {} + constructor(readonly client: TelegramClient, readonly raw: tl.RawHighScore, readonly _peers: PeersIndex) {} private _user?: User /** * User who has scored this score */ get user(): User { - return (this._user ??= new User( - this.client, - this._peers.user(this.raw.userId), - )) + return (this._user ??= new User(this.client, this._peers.user(this.raw.userId))) } /** diff --git a/packages/client/src/types/bots/inline-query.ts b/packages/client/src/types/bots/inline-query.ts index 02435741..9189c20e 100644 --- a/packages/client/src/types/bots/inline-query.ts +++ b/packages/client/src/types/bots/inline-query.ts @@ -34,10 +34,7 @@ export class InlineQuery { * User who sent this query */ get user(): User { - return (this._user ??= new User( - this.client, - this._peers.user(this.raw.userId), - )) + return (this._user ??= new User(this.client, this._peers.user(this.raw.userId))) } /** diff --git a/packages/client/src/types/bots/input/input-inline-message.ts b/packages/client/src/types/bots/input/input-inline-message.ts index 1c5ae27e..b2d24179 100644 --- a/packages/client/src/types/bots/input/input-inline-message.ts +++ b/packages/client/src/types/bots/input/input-inline-message.ts @@ -2,12 +2,7 @@ import { assertNever } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../../client' -import { - InputMediaContact, - InputMediaGeo, - InputMediaGeoLive, - InputMediaVenue, -} from '../../media' +import { InputMediaContact, InputMediaGeo, InputMediaGeoLive, InputMediaVenue } from '../../media' import { FormattedString } from '../../parser' import { BotKeyboard, ReplyMarkup } from '../keyboards' @@ -147,9 +142,7 @@ export namespace BotInlineMessage { * Create an inline message containing * media from the result */ - export function media( - params: Omit = {}, - ): InputInlineMessageMedia { + export function media(params: Omit = {}): InputInlineMessageMedia { const ret = params as tl.Mutable ret.type = 'media' @@ -161,9 +154,7 @@ export namespace BotInlineMessage { * * @param params Additional parameters */ - export function geo( - params: Omit, - ): InputInlineMessageGeo { + export function geo(params: Omit): InputInlineMessageGeo { const ret = params as tl.Mutable ret.type = 'geo' @@ -175,9 +166,7 @@ export namespace BotInlineMessage { * * @param params Additional parameters */ - export function geoLive( - params: Omit, - ): InputInlineMessageGeoLive { + export function geoLive(params: Omit): InputInlineMessageGeoLive { const ret = params as tl.Mutable ret.type = 'geo_live' @@ -187,9 +176,7 @@ export namespace BotInlineMessage { /** * Create an inline message containing a venue */ - export function venue( - params: Omit, - ): InputInlineMessageVenue { + export function venue(params: Omit): InputInlineMessageVenue { const ret = params as tl.Mutable ret.type = 'venue' @@ -200,9 +187,7 @@ export namespace BotInlineMessage { * Create an inline message containing a game * from the inline result */ - export function game( - params: Omit, - ): InputInlineMessageGame { + export function game(params: Omit): InputInlineMessageGame { const ret = params as tl.Mutable ret.type = 'game' @@ -212,9 +197,7 @@ export namespace BotInlineMessage { /** * Create an inline message containing a contact */ - export function contact( - params: Omit, - ): InputInlineMessageContact { + export function contact(params: Omit): InputInlineMessageContact { const ret = params as tl.Mutable ret.type = 'contact' @@ -229,11 +212,7 @@ export namespace BotInlineMessage { ): Promise { switch (obj.type) { case 'text': { - const [message, entities] = await client._parseEntities( - obj.text, - parseMode, - obj.entities, - ) + const [message, entities] = await client._parseEntities(obj.text, parseMode, obj.entities) return { _: 'inputBotInlineMessageText', @@ -243,11 +222,7 @@ export namespace BotInlineMessage { } } case 'media': { - const [message, entities] = await client._parseEntities( - obj.text, - parseMode, - obj.entities, - ) + const [message, entities] = await client._parseEntities(obj.text, parseMode, obj.entities) return { _: 'inputBotInlineMessageMediaAuto', @@ -268,8 +243,7 @@ export namespace BotInlineMessage { // fields will be `undefined` if this is a `geo` heading: (obj as InputMediaGeoLive).heading, period: (obj as InputMediaGeoLive).period, - proximityNotificationRadius: (obj as InputMediaGeoLive) - .proximityNotificationRadius, + proximityNotificationRadius: (obj as InputMediaGeoLive).proximityNotificationRadius, replyMarkup: BotKeyboard._convertToTl(obj.replyMarkup), } case 'venue': 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 b756ca38..e290623e 100644 --- a/packages/client/src/types/bots/input/input-inline-result.ts +++ b/packages/client/src/types/bots/input/input-inline-result.ts @@ -620,10 +620,7 @@ export namespace BotInline { * @param id Inline result ID * @param media Sticker */ - export function sticker( - id: string, - media: string | tl.RawInputDocument, - ): InputInlineResultSticker { + export function sticker(id: string, media: string | tl.RawInputDocument): InputInlineResultSticker { return { id, type: 'sticker', @@ -658,10 +655,7 @@ export namespace BotInline { * @param id Inline result ID * @param params Additional parameters */ - export function geo( - id: string, - params: Omit, - ): InputInlineResultGeo { + export function geo(id: string, params: Omit): InputInlineResultGeo { const ret = params as tl.Mutable ret.id = id ret.type = 'geo' @@ -675,10 +669,7 @@ export namespace BotInline { * @param id Inline result ID * @param params Venue parameters */ - export function venue( - id: string, - params: Omit, - ): InputInlineResultVenue { + export function venue(id: string, params: Omit): InputInlineResultVenue { const ret = params as tl.Mutable ret.id = id ret.type = 'venue' @@ -729,16 +720,8 @@ export namespace BotInline { results: InputInlineResult[], parseMode?: string | null, ): Promise<[boolean, tl.TypeInputBotInlineResult[]]> { - const normalizeThumb = ( - obj: InputInlineResult, - fallback?: string, - ): tl.RawInputWebDocument | undefined => { - if ( - obj.type !== 'voice' && - obj.type !== 'audio' && - obj.type !== 'sticker' && - obj.type !== 'game' - ) { + const normalizeThumb = (obj: InputInlineResult, fallback?: string): tl.RawInputWebDocument | undefined => { + if (obj.type !== 'voice' && obj.type !== 'audio' && obj.type !== 'sticker' && obj.type !== 'game') { if (!obj.thumb || typeof obj.thumb === 'string') { if (!obj.thumb && !fallback) { return undefined @@ -748,10 +731,7 @@ export namespace BotInline { _: 'inputWebDocument', size: 0, url: obj.thumb || fallback!, - mimeType: - obj.type === 'gif' ? - obj.thumbMime ?? obj.mime ?? 'video/mp4' : - 'image/jpeg', + mimeType: obj.type === 'gif' ? obj.thumbMime ?? obj.mime ?? 'video/mp4' : 'image/jpeg', attributes: [], } } @@ -773,11 +753,7 @@ export namespace BotInline { let sendMessage: tl.TypeInputBotInlineMessage if (obj.message) { - sendMessage = await BotInlineMessage._convertToTl( - client, - obj.message, - parseMode, - ) + sendMessage = await BotInlineMessage._convertToTl(client, obj.message, parseMode) } else { let message = obj.title const entities: tl.TypeMessageEntity[] = [ @@ -825,10 +801,7 @@ export namespace BotInline { attributes: [], } : undefined, - thumb: - typeof obj.thumb === 'string' ? - normalizeThumb(obj) : - obj.thumb, + thumb: typeof obj.thumb === 'string' ? normalizeThumb(obj) : obj.thumb, sendMessage, }) continue @@ -837,16 +810,10 @@ export namespace BotInline { let sendMessage: tl.TypeInputBotInlineMessage if (obj.message) { - sendMessage = await BotInlineMessage._convertToTl( - client, - obj.message, - parseMode, - ) + sendMessage = await BotInlineMessage._convertToTl(client, obj.message, parseMode) if (sendMessage._ !== 'inputBotInlineMessageGame') { - throw new MtArgumentError( - 'game inline result must contain a game inline message', - ) + throw new MtArgumentError('game inline result must contain a game inline message') } } else { sendMessage = { @@ -876,11 +843,7 @@ export namespace BotInline { let sendMessage: tl.TypeInputBotInlineMessage if (obj.message) { - sendMessage = await BotInlineMessage._convertToTl( - client, - obj.message, - parseMode, - ) + sendMessage = await BotInlineMessage._convertToTl(client, obj.message, parseMode) } else if (obj.type === 'venue') { if (obj.latitude && obj.longitude) { sendMessage = { @@ -897,15 +860,9 @@ export namespace BotInline { venueType: '', } } else { - throw new MtArgumentError( - 'message or location (lat&lon) bust be supplied for venue inline result', - ) + throw new MtArgumentError('message or location (lat&lon) bust be supplied for venue inline result') } - } else if ( - obj.type === 'video' && - obj.isEmbed && - typeof obj.media === 'string' - ) { + } else if (obj.type === 'video' && obj.isEmbed && typeof obj.media === 'string') { sendMessage = { _: 'inputBotInlineMessageText', message: obj.media, @@ -934,36 +891,26 @@ export namespace BotInline { } } - let media: - | tl.TypeInputWebDocument - | tl.TypeInputDocument - | tl.TypeInputPhoto - | undefined = undefined + let media: tl.TypeInputWebDocument | tl.TypeInputDocument | tl.TypeInputPhoto | undefined = undefined - if ( - obj.type !== 'geo' && - obj.type !== 'venue' && - obj.type !== 'contact' - ) { + if (obj.type !== 'geo' && obj.type !== 'venue' && obj.type !== 'contact') { if (typeof obj.media === 'string') { // file id or url if (obj.media.match(/^https?:\/\//)) { if (obj.type === 'sticker') { - throw new MtArgumentError( - 'sticker inline result cannot contain a URL', - ) + throw new MtArgumentError('sticker inline result cannot contain a URL') } 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 === '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( - 'MIME type must be specified for file inline result', - ) + throw new MtArgumentError('MIME type must be specified for file inline result') } mime = obj.mime @@ -972,9 +919,7 @@ export namespace BotInline { const attributes: tl.TypeDocumentAttribute[] = [] if ( - (obj.type === 'video' || - obj.type === 'gif' || - obj.type === 'photo') && + (obj.type === 'video' || obj.type === 'gif' || obj.type === 'photo') && obj.width && obj.height ) { @@ -992,17 +937,13 @@ 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', duration: obj.duration ?? 0, title: obj.type === 'audio' ? obj.title : '', - performer: - obj.type === 'audio' ? obj.performer : '', + performer: obj.type === 'audio' ? obj.performer : '', }) } @@ -1037,9 +978,7 @@ export namespace BotInline { // but whatever. // ref: https://github.com/tdlib/td/blob/master/td/telegram/InlineQueriesManager.cpp if (obj.type === 'contact') { - title = obj.lastName?.length ? - `${obj.firstName} ${obj.lastName}` : - obj.firstName + title = obj.lastName?.length ? `${obj.firstName} ${obj.lastName}` : obj.firstName } else if (obj.type !== 'sticker') { title = obj.title } diff --git a/packages/client/src/types/bots/keyboard-builder.ts b/packages/client/src/types/bots/keyboard-builder.ts index b9baeb32..cb4de42d 100644 --- a/packages/client/src/types/bots/keyboard-builder.ts +++ b/packages/client/src/types/bots/keyboard-builder.ts @@ -70,10 +70,7 @@ export class BotKeyboardBuilder { if ( this._buttons.length && - (this.maxRowWidth === null || - force || - this._buttons[this._buttons.length - 1].length < - this.maxRowWidth) + (this.maxRowWidth === null || force || this._buttons[this._buttons.length - 1].length < this.maxRowWidth) ) { this._buttons[this._buttons.length - 1].push() } else { @@ -96,9 +93,7 @@ export class BotKeyboardBuilder { /** * Return contents of this builder as a reply keyboard */ - asReply( - params: Omit = {}, - ): ReplyKeyboardMarkup { + asReply(params: Omit = {}): ReplyKeyboardMarkup { const ret = params as tl.Mutable ret.type = 'reply' ret.buttons = this._buttons diff --git a/packages/client/src/types/bots/keyboards.ts b/packages/client/src/types/bots/keyboards.ts index ac702802..b433cc69 100644 --- a/packages/client/src/types/bots/keyboards.ts +++ b/packages/client/src/types/bots/keyboards.ts @@ -7,8 +7,7 @@ import { BotKeyboardBuilder } from './keyboard-builder' /** * Reply keyboard markup */ -export interface ReplyKeyboardMarkup - extends Omit { +export interface ReplyKeyboardMarkup extends Omit { readonly type: 'reply' /** @@ -27,8 +26,7 @@ export interface ReplyKeyboardHide extends Omit { /** * Force the user to send a reply */ -export interface ReplyKeyboardForceReply - extends Omit { +export interface ReplyKeyboardForceReply extends Omit { readonly type: 'force_reply' } @@ -72,9 +70,7 @@ export namespace BotKeyboard { * * @param buttons Two-dimensional array of buttons */ - export function inline( - buttons: tl.TypeKeyboardButton[][], - ): InlineKeyboardMarkup { + export function inline(buttons: tl.TypeKeyboardButton[][]): InlineKeyboardMarkup { return { type: 'inline', buttons, @@ -116,9 +112,7 @@ export namespace BotKeyboard { /** * Force the user to send a reply */ - export function forceReply( - params: Omit = {}, - ): ReplyKeyboardForceReply { + export function forceReply(params: Omit = {}): ReplyKeyboardForceReply { const ret = params as tl.Mutable ret.type = 'force_reply' @@ -147,9 +141,7 @@ export namespace BotKeyboard { * * @param text Button text */ - export function requestContact( - text: string, - ): tl.RawKeyboardButtonRequestPhone { + export function requestContact(text: string): tl.RawKeyboardButtonRequestPhone { return { _: 'keyboardButtonRequestPhone', text, @@ -164,9 +156,7 @@ export namespace BotKeyboard { * * @param text Button text */ - export function requestGeo( - text: string, - ): tl.RawKeyboardButtonRequestGeoLocation { + export function requestGeo(text: string): tl.RawKeyboardButtonRequestGeoLocation { return { _: 'keyboardButtonRequestGeoLocation', text, @@ -182,10 +172,7 @@ export namespace BotKeyboard { * @param text Button text * @param quiz If set, only quiz polls can be sent */ - export function requestPoll( - text: string, - quiz?: boolean, - ): tl.RawKeyboardButtonRequestPoll { + export function requestPoll(text: string, quiz?: boolean): tl.RawKeyboardButtonRequestPoll { return { _: 'keyboardButtonRequestPoll', text, @@ -248,11 +235,7 @@ export namespace BotKeyboard { * If set, pressing the button will insert the bot's username * and the specified inline query in the current chat's input field */ - export function switchInline( - text: string, - query = '', - currentChat?: boolean, - ): tl.RawKeyboardButtonSwitchInline { + export function switchInline(text: string, query = '', currentChat?: boolean): tl.RawKeyboardButtonSwitchInline { return { _: 'keyboardButtonSwitchInline', samePeer: currentChat, @@ -343,10 +326,7 @@ export namespace BotKeyboard { * @param text Button label * @param url WebView URL */ - export function webView( - text: string, - url: string, - ): tl.RawKeyboardButtonWebView { + export function webView(text: string, url: string): tl.RawKeyboardButtonWebView { return { _: 'keyboardButtonWebView', text, @@ -360,10 +340,7 @@ export namespace BotKeyboard { * @param text Text of the button * @param user User to be opened (use {@link TelegramClient.resolvePeer}) */ - export function userProfile( - text: string, - user: tl.TypeInputPeer, - ): tl.RawInputKeyboardButtonUserProfile { + export function userProfile(text: string, user: tl.TypeInputPeer): tl.RawInputKeyboardButtonUserProfile { return { _: 'inputKeyboardButtonUserProfile', text, @@ -401,24 +378,23 @@ export namespace BotKeyboard { } /** @internal */ - export function _rowsTo2d( - rows: tl.RawKeyboardButtonRow[], - ): tl.TypeKeyboardButton[][] { + export function _rowsTo2d(rows: tl.RawKeyboardButtonRow[]): tl.TypeKeyboardButton[][] { return rows.map((it) => it.buttons) } /** @internal */ - export function _2dToRows( - arr: tl.TypeKeyboardButton[][], - inline: boolean, - ): tl.RawKeyboardButtonRow[] { + export function _2dToRows(arr: tl.TypeKeyboardButton[][], inline: boolean): tl.RawKeyboardButtonRow[] { return arr.map((row) => { if (!inline) { // le cringe - row = row.map((btn) => btn._ === 'keyboardButtonWebView' ? ({ - ...btn, - _: 'keyboardButtonSimpleWebView', - }) : btn) + row = row.map((btn) => + btn._ === 'keyboardButtonWebView' ? + { + ...btn, + _: 'keyboardButtonSimpleWebView', + } : + btn, + ) } return { @@ -429,9 +405,7 @@ export namespace BotKeyboard { } /** @internal */ - export function _convertToTl( - obj?: ReplyMarkup, - ): tl.TypeReplyMarkup | undefined { + export function _convertToTl(obj?: ReplyMarkup): tl.TypeReplyMarkup | undefined { if (!obj) return obj if (tl.isAnyReplyMarkup(obj)) return obj diff --git a/packages/client/src/types/calls/discard-reason.ts b/packages/client/src/types/calls/discard-reason.ts index 93c423e9..ad1eea98 100644 --- a/packages/client/src/types/calls/discard-reason.ts +++ b/packages/client/src/types/calls/discard-reason.ts @@ -11,9 +11,7 @@ import { tl } from '@mtcute/tl' export type CallDiscardReason = 'missed' | 'disconnect' | 'hangup' | 'busy' /** @internal */ -export function _callDiscardReasonFromTl( - raw: tl.TypePhoneCallDiscardReason, -): CallDiscardReason { +export function _callDiscardReasonFromTl(raw: tl.TypePhoneCallDiscardReason): CallDiscardReason { switch (raw._) { case 'phoneCallDiscardReasonMissed': return 'missed' @@ -29,9 +27,7 @@ export function _callDiscardReasonFromTl( } /** @internal */ -export function _callDiscardReasonToTl( - r: CallDiscardReason, -): tl.TypePhoneCallDiscardReason { +export function _callDiscardReasonToTl(r: CallDiscardReason): tl.TypePhoneCallDiscardReason { switch (r) { case 'missed': return { _: 'phoneCallDiscardReasonMissed' } diff --git a/packages/client/src/types/conversation.ts b/packages/client/src/types/conversation.ts index d4f0c411..626d689c 100644 --- a/packages/client/src/types/conversation.ts +++ b/packages/client/src/types/conversation.ts @@ -1,16 +1,6 @@ /* eslint-disable dot-notation */ -import { - getMarkedPeerId, - MaybeAsync, - MtArgumentError, - MtTimeoutError, -} from '@mtcute/core' -import { - AsyncLock, - ControllablePromise, - createControllablePromise, - Deque, -} from '@mtcute/core/utils' +import { getMarkedPeerId, MaybeAsync, MtArgumentError, MtTimeoutError } from '@mtcute/core' +import { AsyncLock, ControllablePromise, createControllablePromise, Deque } from '@mtcute/core/utils' import { tl } from '@mtcute/tl' import { TelegramClient } from '../client' @@ -145,9 +135,7 @@ export class Conversation { if (pending && !pending.length) { this.client['_pendingConversations'].delete(this._chatId) } - this.client['_hasConversations'] = Boolean( - this.client['_pendingConversations'].size, - ) + this.client['_hasConversations'] = Boolean(this.client['_pendingConversations'].size) // reset pending status this._queuedNewMessage.clear() @@ -368,14 +356,11 @@ export class Conversation { const msgId = params?.message ?? this._lastMessage if (!msgId) { - throw new MtArgumentError( - 'Provide message for which to wait for reply for', - ) + throw new MtArgumentError('Provide message for which to wait for reply for') } const pred = filter ? - (msg: Message) => - msg.replyToMessageId === msgId ? filter(msg) : false : + (msg: Message) => (msg.replyToMessageId === msgId ? filter(msg) : false) : (msg: Message) => msg.replyToMessageId === msgId return this.waitForNewMessage(pred, params?.timeout) @@ -418,9 +403,7 @@ export class Conversation { const msgId = params?.message ?? this._lastReceivedMessage if (!msgId) { - throw new MtArgumentError( - 'Provide message for which to wait for edit for', - ) + throw new MtArgumentError('Provide message for which to wait for edit for') } const promise = createControllablePromise() @@ -456,10 +439,7 @@ export class Conversation { * @param timeout Timeout for the handler in ms, def. 15 sec. Pass `null` to disable. * When the timeout is reached, `TimeoutError` is thrown. */ - async waitForRead( - message?: number, - timeout: number | null = 15000, - ): Promise { + async waitForRead(message?: number, timeout: number | null = 15000): Promise { if (!this._started) { throw new MtArgumentError("Conversation hasn't started yet") } @@ -467,9 +447,7 @@ export class Conversation { const msgId = message ?? this._lastMessage if (!msgId) { - throw new MtArgumentError( - 'Provide message for which to wait for read for', - ) + throw new MtArgumentError('Provide message for which to wait for read for') } // check if the message is already read diff --git a/packages/client/src/types/errors.ts b/packages/client/src/types/errors.ts index 621ca383..314e0f8b 100644 --- a/packages/client/src/types/errors.ts +++ b/packages/client/src/types/errors.ts @@ -11,16 +11,8 @@ export class MtPeerNotFoundError extends MtcuteError {} * Could not find a message by the provided information */ export class MtMessageNotFoundError extends MtcuteError { - constructor( - readonly peerId: number, - readonly messageId: number, - readonly context?: string, - ) { - super( - `Message${ - context ? ' ' + context : '' - } ${messageId} not found in ${peerId}`, - ) + constructor(readonly peerId: number, readonly messageId: number, readonly context?: string) { + super(`Message${context ? ' ' + context : ''} ${messageId} not found in ${peerId}`) } } @@ -33,9 +25,7 @@ export class MtMessageNotFoundError extends MtcuteError { */ export class MtInvalidPeerTypeError extends MtcuteError { constructor(peer: InputPeerLike, expected: string) { - super( - `Provided identifier ${JSON.stringify(peer)} is not a ${expected}`, - ) + super(`Provided identifier ${JSON.stringify(peer)} is not a ${expected}`) } } diff --git a/packages/client/src/types/files/file-location.ts b/packages/client/src/types/files/file-location.ts index 261d4971..7b612e67 100644 --- a/packages/client/src/types/files/file-location.ts +++ b/packages/client/src/types/files/file-location.ts @@ -32,10 +32,7 @@ export class FileLocation { | tl.TypeInputFileLocation | tl.TypeInputWebFileLocation | Buffer - | (() => - | tl.TypeInputFileLocation - | tl.TypeInputWebFileLocation - | Buffer), + | (() => tl.TypeInputFileLocation | tl.TypeInputWebFileLocation | Buffer), /** * File size in bytes, when available */ @@ -54,9 +51,7 @@ export class FileLocation { * @param params Download parameters * @link TelegramClient.downloadAsIterable */ - downloadIterable( - params?: Partial, - ): AsyncIterableIterator { + downloadIterable(params?: Partial): AsyncIterableIterator { return this.client.downloadAsIterable({ ...params, location: this, @@ -97,10 +92,7 @@ export class FileLocation { * @param params File download parameters * @link TelegramClient.downloadToFile */ - downloadToFile( - filename: string, - params?: Partial, - ): Promise { + downloadToFile(filename: string, params?: Partial): Promise { return this.client.downloadToFile(filename, { ...params, location: this, diff --git a/packages/client/src/types/files/uploaded-file.ts b/packages/client/src/types/files/uploaded-file.ts index 5977510b..3e10a053 100644 --- a/packages/client/src/types/files/uploaded-file.ts +++ b/packages/client/src/types/files/uploaded-file.ts @@ -26,11 +26,5 @@ export interface UploadedFile { /** @internal */ export function isUploadedFile(obj: object): obj is UploadedFile { - return ( - obj && - typeof obj === 'object' && - 'inputFile' in obj && - 'size' in obj && - 'mime' in obj - ) + return obj && typeof obj === 'object' && 'inputFile' in obj && 'size' in obj && 'mime' in obj } diff --git a/packages/client/src/types/files/utils.ts b/packages/client/src/types/files/utils.ts index bd66a1be..304175ea 100644 --- a/packages/client/src/types/files/utils.ts +++ b/packages/client/src/types/files/utils.ts @@ -62,11 +62,7 @@ export interface FileDownloadParameters { * File location which should be downloaded. * You can also provide TDLib and Bot API compatible File ID */ - location: - | tl.TypeInputFileLocation - | tl.TypeInputWebFileLocation - | FileLocation - | string + location: tl.TypeInputFileLocation | tl.TypeInputWebFileLocation | FileLocation | string /** * Total file size, if known. diff --git a/packages/client/src/types/files/web-document.ts b/packages/client/src/types/files/web-document.ts index 5b9f42d1..ca798879 100644 --- a/packages/client/src/types/files/web-document.ts +++ b/packages/client/src/types/files/web-document.ts @@ -6,9 +6,7 @@ import { makeInspectable } from '../utils' import { FileLocation } from './file-location' const STUB_LOCATION = () => { - throw new MtArgumentError( - 'This web document is not downloadable through Telegram', - ) + throw new MtArgumentError('This web document is not downloadable through Telegram') } /** diff --git a/packages/client/src/types/media/audio.ts b/packages/client/src/types/media/audio.ts index 4a16906a..377a482b 100644 --- a/packages/client/src/types/media/audio.ts +++ b/packages/client/src/types/media/audio.ts @@ -15,11 +15,7 @@ export class Audio extends RawDocument { return tdFileId.FileType.Audio } - constructor( - client: TelegramClient, - doc: tl.RawDocument, - readonly attr: tl.RawDocumentAttributeAudio, - ) { + constructor(client: TelegramClient, doc: tl.RawDocument, readonly attr: tl.RawDocumentAttributeAudio) { super(client, doc) } diff --git a/packages/client/src/types/media/document-utils.ts b/packages/client/src/types/media/document-utils.ts index 48e5d54d..5b22a666 100644 --- a/packages/client/src/types/media/document-utils.ts +++ b/packages/client/src/types/media/document-utils.ts @@ -7,37 +7,23 @@ import { Sticker } from './sticker' import { Video } from './video' import { Voice } from './voice' -export type ParsedDocument = - | Sticker - | Voice - | Audio - | Video - | Document +export type ParsedDocument = Sticker | Voice | Audio | Video | Document /** @internal */ -export function parseDocument( - client: TelegramClient, - doc: tl.RawDocument, -): ParsedDocument { +export function parseDocument(client: TelegramClient, doc: tl.RawDocument): ParsedDocument { const stickerAttr = doc.attributes.find( - (a) => - a._ === 'documentAttributeSticker' || - a._ === 'documentAttributeCustomEmoji', + (a) => a._ === 'documentAttributeSticker' || a._ === 'documentAttributeCustomEmoji', ) if (stickerAttr) { const sz = doc.attributes.find( - (it) => - it._ === 'documentAttributeImageSize' || - it._ === 'documentAttributeVideo', + (it) => it._ === 'documentAttributeImageSize' || it._ === 'documentAttributeVideo', )! as tl.RawDocumentAttributeImageSize | tl.RawDocumentAttributeVideo return new Sticker( client, doc, - stickerAttr as - | tl.RawDocumentAttributeSticker - | tl.RawDocumentAttributeCustomEmoji, + stickerAttr as tl.RawDocumentAttributeSticker | tl.RawDocumentAttributeCustomEmoji, sz, ) } diff --git a/packages/client/src/types/media/document.ts b/packages/client/src/types/media/document.ts index 7cf7917d..c1ec6378 100644 --- a/packages/client/src/types/media/document.ts +++ b/packages/client/src/types/media/document.ts @@ -37,12 +37,8 @@ export abstract class RawDocument extends FileLocation { */ get fileName(): string | null { if (this._fileName === undefined) { - const attr = this.raw.attributes.find( - (it) => it._ === 'documentAttributeFilename', - ) - this._fileName = attr ? - (attr as tl.RawDocumentAttributeFilename).fileName : - null + const attr = this.raw.attributes.find((it) => it._ === 'documentAttributeFilename') + this._fileName = attr ? (attr as tl.RawDocumentAttributeFilename).fileName : null } return this._fileName @@ -72,12 +68,8 @@ export abstract class RawDocument extends FileLocation { if (!this._thumbnails) { const arr: Thumbnail[] = [] - this.raw.thumbs?.forEach((sz) => - arr.push(new Thumbnail(this.client, this.raw, sz)), - ) - this.raw.videoThumbs?.forEach((sz) => - arr.push(new Thumbnail(this.client, this.raw, sz)), - ) + this.raw.thumbs?.forEach((sz) => arr.push(new Thumbnail(this.client, this.raw, sz))) + this.raw.videoThumbs?.forEach((sz) => arr.push(new Thumbnail(this.client, this.raw, sz))) this._thumbnails = arr } @@ -97,10 +89,9 @@ export abstract class RawDocument extends FileLocation { getThumbnail(type: string): Thumbnail | null { return ( this.thumbnails.find((it) => { - if ( - it.raw._ === 'videoSizeEmojiMarkup' || - it.raw._ === 'videoSizeStickerMarkup' - ) { return false } + if (it.raw._ === 'videoSizeEmojiMarkup' || it.raw._ === 'videoSizeStickerMarkup') { + return false + } return it.raw.type === type }) ?? null diff --git a/packages/client/src/types/media/game.ts b/packages/client/src/types/media/game.ts index 8a056cb2..64db1ef8 100644 --- a/packages/client/src/types/media/game.ts +++ b/packages/client/src/types/media/game.ts @@ -56,18 +56,14 @@ export class Game { if (this.game.document?._ !== 'document') return null if (this._animation === undefined) { - const attr = this.game.document.attributes.find( - (it) => it._ === 'documentAttributeVideo', - ) as tl.RawDocumentAttributeVideo | undefined + const attr = this.game.document.attributes.find((it) => it._ === 'documentAttributeVideo') as + | tl.RawDocumentAttributeVideo + | undefined if (!attr) { this._animation = null } else { - this._animation = new Video( - this.client, - this.game.document, - attr, - ) + this._animation = new Video(this.client, this.game.document, attr) } } diff --git a/packages/client/src/types/media/input-media.ts b/packages/client/src/types/media/input-media.ts index 950d847b..a06bf512 100644 --- a/packages/client/src/types/media/input-media.ts +++ b/packages/client/src/types/media/input-media.ts @@ -570,10 +570,7 @@ export type InputMediaLike = // eslint-disable-next-line @typescript-eslint/no-namespace export namespace InputMedia { - export type OmitTypeAndFile< - T extends InputMediaLike, - K extends keyof T = never - > = Omit + export type OmitTypeAndFile = Omit /** * Create an animation to be sent @@ -581,10 +578,7 @@ export namespace InputMedia { * @param file Animation * @param params Additional parameters */ - export function animation( - file: InputFileLike, - params: OmitTypeAndFile = {}, - ): InputMediaVideo { + export function animation(file: InputFileLike, params: OmitTypeAndFile = {}): InputMediaVideo { const ret = params as tl.Mutable ret.type = 'video' ret.file = file @@ -599,10 +593,7 @@ export namespace InputMedia { * @param file Audio file * @param params Additional parameters */ - export function audio( - file: InputFileLike, - params: OmitTypeAndFile = {}, - ): InputMediaAudio { + export function audio(file: InputFileLike, params: OmitTypeAndFile = {}): InputMediaAudio { const ret = params as tl.Mutable ret.type = 'audio' ret.file = file @@ -633,10 +624,7 @@ export namespace InputMedia { * @param file Photo * @param params Additional parameters */ - export function photo( - file: InputFileLike, - params: OmitTypeAndFile = {}, - ): InputMediaPhoto { + export function photo(file: InputFileLike, params: OmitTypeAndFile = {}): InputMediaPhoto { const ret = params as tl.Mutable ret.type = 'photo' ret.file = file @@ -650,10 +638,7 @@ export namespace InputMedia { * @param file Video * @param params Additional parameters */ - export function video( - file: InputFileLike, - params: OmitTypeAndFile = {}, - ): InputMediaVideo { + export function video(file: InputFileLike, params: OmitTypeAndFile = {}): InputMediaVideo { const ret = params as tl.Mutable ret.type = 'video' ret.file = file @@ -667,10 +652,7 @@ export namespace InputMedia { * @param file Voice note * @param params Additional parameters */ - export function voice( - file: InputFileLike, - params: OmitTypeAndFile = {}, - ): InputMediaVoice { + export function voice(file: InputFileLike, params: OmitTypeAndFile = {}): InputMediaVoice { const ret = params as tl.Mutable ret.type = 'voice' ret.file = file @@ -684,10 +666,7 @@ export namespace InputMedia { * @param file Sticker * @param params Additional parameters */ - export function sticker( - file: InputFileLike, - params: OmitTypeAndFile = {}, - ): InputMediaSticker { + export function sticker(file: InputFileLike, params: OmitTypeAndFile = {}): InputMediaSticker { const ret = params as tl.Mutable ret.type = 'sticker' ret.file = file @@ -700,9 +679,7 @@ export namespace InputMedia { * * @param params Venue parameters */ - export function venue( - params: OmitTypeAndFile, - ): InputMediaVenue { + export function venue(params: OmitTypeAndFile): InputMediaVenue { const ret = params as tl.Mutable ret.type = 'venue' @@ -739,10 +716,7 @@ export namespace InputMedia { export function geoLive( latitude: number, longitude: number, - params: OmitTypeAndFile< - InputMediaGeoLive, - 'latitude' | 'longitude' - > = {}, + params: OmitTypeAndFile = {}, ): InputMediaGeoLive { const ret = params as tl.Mutable ret.type = 'geo_live' @@ -773,9 +747,7 @@ export namespace InputMedia { * * @param params Contact parameters */ - export function contact( - params: OmitTypeAndFile, - ): InputMediaContact { + export function contact(params: OmitTypeAndFile): InputMediaContact { const ret = params as tl.Mutable ret.type = 'contact' @@ -799,9 +771,7 @@ export namespace InputMedia { * * @param params Invoice parameters */ - export function invoice( - params: OmitTypeAndFile, - ): InputMediaInvoice { + export function invoice(params: OmitTypeAndFile): InputMediaInvoice { const ret = params as tl.Mutable ret.type = 'invoice' @@ -813,9 +783,7 @@ export namespace InputMedia { * * @param params Poll parameters */ - export function poll( - params: OmitTypeAndFile, - ): InputMediaPoll { + export function poll(params: OmitTypeAndFile): InputMediaPoll { const ret = params as tl.Mutable ret.type = 'poll' @@ -827,9 +795,7 @@ export namespace InputMedia { * * @param params Quiz parameters */ - export function quiz( - params: OmitTypeAndFile, - ): InputMediaQuiz { + export function quiz(params: OmitTypeAndFile): InputMediaQuiz { const ret = params as tl.Mutable ret.type = 'quiz' @@ -847,10 +813,7 @@ export namespace InputMedia { * @param file The media file * @param params Additional parameters */ - export function auto( - file: InputFileLike, - params: OmitTypeAndFile = {}, - ): InputMediaAuto { + export function auto(file: InputFileLike, params: OmitTypeAndFile = {}): InputMediaAuto { const ret = params as tl.Mutable ret.type = 'auto' ret.file = file diff --git a/packages/client/src/types/media/invoice.ts b/packages/client/src/types/media/invoice.ts index d8e58173..055528d2 100644 --- a/packages/client/src/types/media/invoice.ts +++ b/packages/client/src/types/media/invoice.ts @@ -16,10 +16,7 @@ import { Thumbnail } from './thumbnail' export type InvoiceExtendedMediaState = 'none' | 'preview' | 'full' export class InvoiceExtendedMediaPreview { - constructor( - public readonly client: TelegramClient, - public readonly raw: tl.RawMessageExtendedMediaPreview, - ) {} + constructor(public readonly client: TelegramClient, public readonly raw: tl.RawMessageExtendedMediaPreview) {} /** * Width of the preview, in pixels (if available, else 0) @@ -41,11 +38,7 @@ export class InvoiceExtendedMediaPreview { return null } - return (this._thumbnail ??= new Thumbnail( - this.client, - this.raw, - this.raw.thumb, - )) + return (this._thumbnail ??= new Thumbnail(this.client, this.raw, this.raw.thumb)) } /** @@ -63,10 +56,7 @@ export class InvoiceExtendedMediaPreview { export class Invoice { readonly type = 'invoice' as const - constructor( - readonly client: TelegramClient, - readonly raw: tl.RawMessageMediaInvoice, - ) {} + constructor(readonly client: TelegramClient, readonly raw: tl.RawMessageMediaInvoice) {} /** * Whether the shipping address was requested @@ -164,10 +154,7 @@ export class Invoice { throw new MtArgumentError('No extended media preview available') } - return (this._extendedMediaPreview ??= new InvoiceExtendedMediaPreview( - this.client, - this.raw.extendedMedia, - )) + return (this._extendedMediaPreview ??= new InvoiceExtendedMediaPreview(this.client, this.raw.extendedMedia)) } private _extendedMedia?: MessageMedia @@ -181,11 +168,7 @@ export class Invoice { throw new MtArgumentError('No extended media available') } - return (this._extendedMedia ??= _messageMediaFromTl( - this.client, - null, - this.raw.extendedMedia.media, - )) + return (this._extendedMedia ??= _messageMediaFromTl(this.client, null, this.raw.extendedMedia.media)) } /** diff --git a/packages/client/src/types/media/location.ts b/packages/client/src/types/media/location.ts index 5a5c75d1..bc9dabe4 100644 --- a/packages/client/src/types/media/location.ts +++ b/packages/client/src/types/media/location.ts @@ -8,10 +8,7 @@ import { makeInspectable } from '../utils' * A point on the map */ export class RawLocation { - constructor( - readonly client: TelegramClient, - readonly geo: tl.RawGeoPoint, - ) {} + constructor(readonly client: TelegramClient, readonly geo: tl.RawGeoPoint) {} /** * Geo point latitude @@ -110,10 +107,7 @@ export class Location extends RawLocation { export class LiveLocation extends RawLocation { readonly type = 'live_location' as const - constructor( - client: TelegramClient, - readonly live: tl.RawMessageMediaGeoLive, - ) { + constructor(client: TelegramClient, readonly live: tl.RawMessageMediaGeoLive) { super(client, live.geo as tl.RawGeoPoint) } diff --git a/packages/client/src/types/media/photo.ts b/packages/client/src/types/media/photo.ts index 5d35200c..73980eed 100644 --- a/packages/client/src/types/media/photo.ts +++ b/packages/client/src/types/media/photo.ts @@ -37,9 +37,9 @@ export class Photo extends FileLocation { let bestSize: tl.RawPhotoSize | tl.RawPhotoSizeProgressive - const progressive = raw.sizes.find( - (it) => it._ === 'photoSizeProgressive', - ) as tl.RawPhotoSizeProgressive | undefined + const progressive = raw.sizes.find((it) => it._ === 'photoSizeProgressive') as + | tl.RawPhotoSizeProgressive + | undefined if (progressive) { location.thumbSize = progressive.type @@ -87,11 +87,7 @@ export class Photo extends FileLocation { * Whether this photo is an animated profile picture */ get isAnimatedAvatar(): boolean { - return Boolean( - this.raw.videoSizes?.some( - (s) => s._ === 'videoSize' && s.type === 'u', - ), - ) + return Boolean(this.raw.videoSizes?.some((s) => s._ === 'videoSize' && s.type === 'u')) } /** @@ -99,11 +95,7 @@ export class Photo extends FileLocation { */ get isMarkupAvatar(): boolean { return Boolean( - this.raw.videoSizes?.some( - (s) => - s._ === 'videoSizeEmojiMarkup' || - s._ === 'videoSizeStickerMarkup', - ), + this.raw.videoSizes?.some((s) => s._ === 'videoSizeEmojiMarkup' || s._ === 'videoSizeStickerMarkup'), ) } @@ -116,12 +108,8 @@ export class Photo extends FileLocation { */ get thumbnails(): ReadonlyArray { if (!this._thumbnails) { - this._thumbnails = this.raw.sizes.map( - (sz) => new Thumbnail(this.client, this.raw, sz), - ) - this.raw.videoSizes?.forEach((sz) => - this._thumbnails!.push(new Thumbnail(this.client, this.raw, sz)), - ) + this._thumbnails = this.raw.sizes.map((sz) => new Thumbnail(this.client, this.raw, sz)) + this.raw.videoSizes?.forEach((sz) => this._thumbnails!.push(new Thumbnail(this.client, this.raw, sz))) } return this._thumbnails @@ -168,9 +156,7 @@ export class Photo extends FileLocation { throw new MtArgumentError('Cannot get File ID for this photo') } - this._uniqueFileId = this.getThumbnail( - this._bestSize.type, - )!.uniqueFileId + this._uniqueFileId = this.getThumbnail(this._bestSize.type)!.uniqueFileId } return this._uniqueFileId @@ -201,8 +187,4 @@ export class Photo extends FileLocation { } } -makeInspectable( - Photo, - ['fileSize', 'dcId', 'width', 'height'], - ['inputMedia', 'inputPhoto'], -) +makeInspectable(Photo, ['fileSize', 'dcId', 'width', 'height'], ['inputMedia', 'inputPhoto']) diff --git a/packages/client/src/types/media/poll.ts b/packages/client/src/types/media/poll.ts index 3e93942e..1cb012b9 100644 --- a/packages/client/src/types/media/poll.ts +++ b/packages/client/src/types/media/poll.ts @@ -172,9 +172,7 @@ export class Poll { unparseSolution(parseMode?: string | null): string | null { if (!this.solution) return null - return this.client - .getParseMode(parseMode) - .unparse(this.solution, this.solutionEntities!) + return this.client.getParseMode(parseMode).unparse(this.solution, this.solutionEntities!) } /** diff --git a/packages/client/src/types/media/sticker.ts b/packages/client/src/types/media/sticker.ts index 9292881a..0dcf1764 100644 --- a/packages/client/src/types/media/sticker.ts +++ b/packages/client/src/types/media/sticker.ts @@ -65,12 +65,8 @@ export class Sticker extends RawDocument { constructor( client: TelegramClient, doc: tl.RawDocument, - readonly attr: - | tl.RawDocumentAttributeSticker - | tl.RawDocumentAttributeCustomEmoji, - readonly attr2?: - | tl.RawDocumentAttributeImageSize - | tl.RawDocumentAttributeVideo, + readonly attr: tl.RawDocumentAttributeSticker | tl.RawDocumentAttributeCustomEmoji, + readonly attr2?: tl.RawDocumentAttributeImageSize | tl.RawDocumentAttributeVideo, ) { super(client, doc) } @@ -94,11 +90,7 @@ export class Sticker extends RawDocument { * (has premium fullscreen animation) */ get isPremiumSticker(): boolean { - return Boolean( - this.raw.videoThumbs?.some( - (s) => s._ === 'videoSize' && s.type === 'f', - ), - ) + return Boolean(this.raw.videoThumbs?.some((s) => s._ === 'videoSize' && s.type === 'f')) } /** @@ -108,10 +100,7 @@ export class Sticker extends RawDocument { * that Telegram treats as a sticker. */ get isValidSticker(): boolean { - return ( - this.attr2 !== undefined && - (this.attr2.w === 512 || this.attr2.h === 512) - ) + return this.attr2 !== undefined && (this.attr2.w === 512 || this.attr2.h === 512) } /** @@ -139,9 +128,7 @@ export class Sticker extends RawDocument { * > Not sure if there are any such stickers currently. */ get customEmojiFree(): boolean { - return this.attr._ === 'documentAttributeCustomEmoji' ? - this.attr.free ?? false : - false + return this.attr._ === 'documentAttributeCustomEmoji' ? this.attr.free ?? false : false } /** @@ -177,9 +164,7 @@ export class Sticker extends RawDocument { return 'video' } - return this.mimeType === 'application/x-tgsticker' ? - 'animated' : - 'static' + return this.mimeType === 'application/x-tgsticker' ? 'animated' : 'static' } /** @@ -193,9 +178,7 @@ export class Sticker extends RawDocument { * Input sticker set that it associated with this sticker, if available. */ get inputStickerSet(): tl.TypeInputStickerSet | null { - return this.attr.stickerset._ === 'inputStickerSetEmpty' ? - null : - this.attr.stickerset + return this.attr.stickerset._ === 'inputStickerSetEmpty' ? null : this.attr.stickerset } private _maskPosition?: MaskPosition @@ -203,10 +186,7 @@ export class Sticker extends RawDocument { * Position where this mask should be placed */ get maskPosition(): MaskPosition | null { - if ( - this.attr._ !== 'documentAttributeSticker' || - !this.attr.maskCoords - ) { + if (this.attr._ !== 'documentAttributeSticker' || !this.attr.maskCoords) { return null } @@ -244,8 +224,7 @@ export class Sticker extends RawDocument { const set = await this.getStickerSet() if (!set) return '' - return set.stickers.find((it) => it.sticker.raw.id.eq(this.raw.id))! - .emoji + return set.stickers.find((it) => it.sticker.raw.id.eq(this.raw.id))!.emoji } } diff --git a/packages/client/src/types/media/thumbnail.ts b/packages/client/src/types/media/thumbnail.ts index e40b788d..c9c31722 100644 --- a/packages/client/src/types/media/thumbnail.ts +++ b/packages/client/src/types/media/thumbnail.ts @@ -6,11 +6,7 @@ import { tdFileId as td, toFileId, toUniqueFileId } from '@mtcute/file-id' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' -import { - inflateSvgPath, - strippedPhotoToJpg, - svgPathToFile, -} from '../../utils/file-utils' +import { inflateSvgPath, strippedPhotoToJpg, svgPathToFile } from '../../utils/file-utils' import { FileLocation } from '../files' import { makeInspectable } from '../utils' @@ -60,35 +56,20 @@ export class Thumbnail extends FileLocation { readonly height: number private _path?: string - private _media: - | tl.RawPhoto - | tl.RawDocument - | tl.RawStickerSet - | tl.RawMessageExtendedMediaPreview + private _media: tl.RawPhoto | tl.RawDocument | tl.RawStickerSet | tl.RawMessageExtendedMediaPreview constructor( client: TelegramClient, - media: - | tl.RawPhoto - | tl.RawDocument - | tl.RawStickerSet - | tl.RawMessageExtendedMediaPreview, + media: tl.RawPhoto | tl.RawDocument | tl.RawStickerSet | tl.RawMessageExtendedMediaPreview, sz: tl.TypePhotoSize | tl.TypeVideoSize, ) { switch (sz._) { case 'photoSizeEmpty': case 'photoCachedSize': - throw new MtTypeAssertionError( - 'sz', - 'not (photoSizeEmpty | photoCachedSize)', - sz._, - ) + throw new MtTypeAssertionError('sz', 'not (photoSizeEmpty | photoCachedSize)', sz._) } - let location: - | tl.TypeInputFileLocation - | Buffer - | (() => tl.TypeInputFileLocation | Buffer) + let location: tl.TypeInputFileLocation | Buffer | (() => tl.TypeInputFileLocation | Buffer) let size let width let height: number @@ -107,9 +88,7 @@ export class Thumbnail extends FileLocation { case 'videoSizeEmojiMarkup': case 'videoSizeStickerMarkup': location = () => { - throw new MtArgumentError( - 'Cannot download thumbnail with emoji/sticker markup, try other size', - ) + throw new MtArgumentError('Cannot download thumbnail with emoji/sticker markup, try other size') } width = height = NaN size = Infinity @@ -127,17 +106,10 @@ export class Thumbnail extends FileLocation { } } else if (media._ === 'messageExtendedMediaPreview') { // according to tdlib and tdesktop sources, sz can only be photoStrippedSize - throw new MtTypeAssertionError( - 'messageExtendedMediaPreview#thumb', - 'photoStrippedSize', - sz._, - ) + throw new MtTypeAssertionError('messageExtendedMediaPreview#thumb', 'photoStrippedSize', sz._) } else { location = { - _: - media._ === 'photo' ? - 'inputPhotoFileLocation' : - 'inputDocumentFileLocation', + _: media._ === 'photo' ? 'inputPhotoFileLocation' : 'inputDocumentFileLocation', id: media.id, fileReference: media.fileReference, accessHash: media.accessHash, @@ -146,10 +118,7 @@ export class Thumbnail extends FileLocation { } width = sz.w height = sz.h - size = - sz._ === 'photoSizeProgressive' ? - Math.max(...sz.sizes) : - sz.size + size = sz._ === 'photoSizeProgressive' ? Math.max(...sz.sizes) : sz.size break } @@ -219,14 +188,10 @@ export class Thumbnail extends FileLocation { get fileId(): string { if (!this._fileId) { if ( - (this.raw._ !== 'photoSize' && - this.raw._ !== 'photoSizeProgressive' && - this.raw._ !== 'videoSize') || + (this.raw._ !== 'photoSize' && this.raw._ !== 'photoSizeProgressive' && this.raw._ !== 'videoSize') || this._media._ === 'messageExtendedMediaPreview' // just for type safety ) { - throw new MtArgumentError( - `Cannot generate a file ID for "${this.type}"`, - ) + throw new MtArgumentError(`Cannot generate a file ID for "${this.type}"`) } if (this._media._ === 'stickerSet') { @@ -248,10 +213,7 @@ export class Thumbnail extends FileLocation { }) } else { this._fileId = toFileId({ - type: - this._media._ === 'photo' ? - td.FileType.Photo : - td.FileType.Thumbnail, + type: this._media._ === 'photo' ? td.FileType.Photo : td.FileType.Thumbnail, dcId: this.dcId!, fileReference: this._media.fileReference, location: { @@ -260,12 +222,8 @@ export class Thumbnail extends FileLocation { accessHash: this._media.accessHash, source: { _: 'thumbnail', - fileType: - this._media._ === 'photo' ? - td.FileType.Photo : - td.FileType.Thumbnail, - thumbnailType: - this.raw.type === 'u' ? '\x00' : this.raw.type, + fileType: this._media._ === 'photo' ? td.FileType.Photo : td.FileType.Thumbnail, + thumbnailType: this.raw.type === 'u' ? '\x00' : this.raw.type, }, }, }) @@ -282,14 +240,10 @@ export class Thumbnail extends FileLocation { get uniqueFileId(): string { if (!this._uniqueFileId) { if ( - (this.raw._ !== 'photoSize' && - this.raw._ !== 'photoSizeProgressive' && - this.raw._ !== 'videoSize') || + (this.raw._ !== 'photoSize' && this.raw._ !== 'photoSizeProgressive' && this.raw._ !== 'videoSize') || this._media._ === 'messageExtendedMediaPreview' // just for type safety ) { - throw new MtArgumentError( - `Cannot generate a unique file ID for "${this.type}"`, - ) + throw new MtArgumentError(`Cannot generate a unique file ID for "${this.type}"`) } if (this._media._ === 'stickerSet') { @@ -305,20 +259,14 @@ export class Thumbnail extends FileLocation { }) } else { this._uniqueFileId = toUniqueFileId( - this._media._ === 'photo' ? - td.FileType.Photo : - td.FileType.Thumbnail, + this._media._ === 'photo' ? td.FileType.Photo : td.FileType.Thumbnail, { _: 'photo', id: this._media.id, source: { _: 'thumbnail', - fileType: - this._media._ === 'photo' ? - td.FileType.Photo : - td.FileType.Thumbnail, - thumbnailType: - this.raw.type === 'u' ? '\x00' : this.raw.type, + fileType: this._media._ === 'photo' ? td.FileType.Photo : td.FileType.Thumbnail, + thumbnailType: this.raw.type === 'u' ? '\x00' : this.raw.type, }, }, ) diff --git a/packages/client/src/types/media/venue.ts b/packages/client/src/types/media/venue.ts index 2aeb73b4..5759d02a 100644 --- a/packages/client/src/types/media/venue.ts +++ b/packages/client/src/types/media/venue.ts @@ -30,10 +30,7 @@ export interface VenueSource { export class Venue { readonly type = 'venue' as const - constructor( - readonly client: TelegramClient, - readonly raw: tl.RawMessageMediaVenue, - ) {} + constructor(readonly client: TelegramClient, readonly raw: tl.RawMessageMediaVenue) {} private _location?: Location /** diff --git a/packages/client/src/types/media/video.ts b/packages/client/src/types/media/video.ts index 41667862..26829de8 100644 --- a/packages/client/src/types/media/video.ts +++ b/packages/client/src/types/media/video.ts @@ -23,9 +23,7 @@ export class Video extends RawDocument { constructor( client: TelegramClient, doc: tl.RawDocument, - readonly attr: - | tl.RawDocumentAttributeVideo - | tl.RawDocumentAttributeImageSize, + readonly attr: tl.RawDocumentAttributeVideo | tl.RawDocumentAttributeImageSize, ) { super(client, doc) } @@ -61,18 +59,14 @@ export class Video extends RawDocument { get isAnimation(): boolean { return (this._isAnimation ??= this.attr._ === 'documentAttributeImageSize' || - this.raw.attributes.some( - (it) => it._ === 'documentAttributeAnimated', - )) + this.raw.attributes.some((it) => it._ === 'documentAttributeAnimated')) } /** * Whether this video is a round video message (aka video note) */ get isRound(): boolean { - return ( - this.attr._ === 'documentAttributeVideo' && Boolean(this.attr.roundMessage) - ) + return this.attr._ === 'documentAttributeVideo' && Boolean(this.attr.roundMessage) } /** diff --git a/packages/client/src/types/media/voice.ts b/packages/client/src/types/media/voice.ts index 017efa6c..82040108 100644 --- a/packages/client/src/types/media/voice.ts +++ b/packages/client/src/types/media/voice.ts @@ -16,11 +16,7 @@ export class Voice extends RawDocument { return tdFileId.FileType.VoiceNote } - constructor( - client: TelegramClient, - doc: tl.RawDocument, - readonly attr: tl.RawDocumentAttributeAudio, - ) { + constructor(client: TelegramClient, doc: tl.RawDocument, readonly attr: tl.RawDocumentAttributeAudio) { super(client, doc) } @@ -42,8 +38,4 @@ export class Voice extends RawDocument { } } -makeInspectable( - Voice, - ['fileSize', 'dcId'], - ['inputMedia', 'inputDocument', 'waveform'], -) +makeInspectable(Voice, ['fileSize', 'dcId'], ['inputMedia', 'inputDocument', 'waveform']) diff --git a/packages/client/src/types/messages/dialog.ts b/packages/client/src/types/messages/dialog.ts index 774fdc13..dce60760 100644 --- a/packages/client/src/types/messages/dialog.ts +++ b/packages/client/src/types/messages/dialog.ts @@ -28,10 +28,7 @@ export class Dialog { * @param dialogs Dialogs list * @param folder If passed, status of pin will be checked against this folder, and not globally */ - static findPinned( - dialogs: Dialog[], - folder?: tl.RawDialogFilter, - ): Dialog[] { + static findPinned(dialogs: Dialog[], folder?: tl.RawDialogFilter): Dialog[] { if (folder) { const index: Record = {} folder.pinnedPeers.forEach((peer) => { @@ -51,10 +48,7 @@ export class Dialog { * @param folder Folder to filter for * @param excludePinned Whether to exclude pinned folders */ - static filterFolder( - folder: tl.TypeDialogFilter, - excludePinned = true, - ): (val: Dialog) => boolean { + static filterFolder(folder: tl.TypeDialogFilter, excludePinned = true): (val: Dialog) => boolean { if (folder._ === 'dialogFilterDefault') { return () => true } @@ -110,17 +104,10 @@ export class Dialog { if (folder.contacts && chatType === 'private' && chat.isContact) { return true } - if ( - folder.nonContacts && - chatType === 'private' && - !chat.isContact - ) { + if (folder.nonContacts && chatType === 'private' && !chat.isContact) { return true } - if ( - folder.groups && - (chatType === 'group' || chatType === 'supergroup') - ) { + if (folder.groups && (chatType === 'group' || chatType === 'supergroup')) { return true } if (folder.broadcasts && chatType === 'channel') return true @@ -180,9 +167,7 @@ export class Dialog { switch (peer._) { case 'peerChannel': case 'peerChat': - chat = this._peers.chat( - peer._ === 'peerChannel' ? peer.channelId : peer.chatId, - ) + chat = this._peers.chat(peer._ === 'peerChannel' ? peer.channelId : peer.chatId) break default: chat = this._peers.user(peer.userId) @@ -204,11 +189,7 @@ export class Dialog { const cid = this.chat.id if (cid in this._messages) { - this._lastMessage = new Message( - this.client, - this._messages[cid], - this._peers, - ) + this._lastMessage = new Message(this.client, this._messages[cid], this._peers) } else { throw new MtMessageNotFoundError(cid, 0) } @@ -259,11 +240,7 @@ export class Dialog { get draftMessage(): DraftMessage | null { if (this._draftMessage === undefined) { if (this.raw.draft?._ === 'draftMessage') { - this._draftMessage = new DraftMessage( - this.client, - this.raw.draft, - this.chat.inputPeer, - ) + this._draftMessage = new DraftMessage(this.client, this.raw.draft, this.chat.inputPeer) } else { this._draftMessage = null } diff --git a/packages/client/src/types/messages/draft-message.ts b/packages/client/src/types/messages/draft-message.ts index 20b14139..d06c03ef 100644 --- a/packages/client/src/types/messages/draft-message.ts +++ b/packages/client/src/types/messages/draft-message.ts @@ -11,11 +11,7 @@ import { MessageEntity } from './message-entity' * A draft message */ export class DraftMessage { - constructor( - readonly client: TelegramClient, - readonly raw: tl.RawDraftMessage, - readonly _chatId: InputPeerLike, - ) {} + constructor(readonly client: TelegramClient, readonly raw: tl.RawDraftMessage, readonly _chatId: InputPeerLike) {} /** * Text of the draft message @@ -93,10 +89,7 @@ export class DraftMessage { * @param params Additional sending parameters * @link TelegramClient.sendMedia */ - sendWithMedia( - media: InputMediaLike, - params?: Parameters[2], - ): Promise { + sendWithMedia(media: InputMediaLike, params?: Parameters[2]): Promise { return this.client.sendMedia(this._chatId, media, { clearDraft: true, replyTo: this.raw.replyToMsgId, diff --git a/packages/client/src/types/messages/message-action.ts b/packages/client/src/types/messages/message-action.ts index 36d3f767..e6c365f0 100644 --- a/packages/client/src/types/messages/message-action.ts +++ b/packages/client/src/types/messages/message-action.ts @@ -278,10 +278,7 @@ export type MessageAction = | null /** @internal */ -export function _messageActionFromTl( - this: Message, - act: tl.TypeMessageAction, -): MessageAction { +export function _messageActionFromTl(this: Message, act: tl.TypeMessageAction): MessageAction { switch (act._) { case 'messageActionChatCreate': return { @@ -343,10 +340,7 @@ export function _messageActionFromTl( users: act.users, } case 'messageActionChatDeleteUser': - if ( - this.raw.fromId?._ === 'peerUser' && - act.userId === this.raw.fromId.userId - ) { + if (this.raw.fromId?._ === 'peerUser' && act.userId === this.raw.fromId.userId) { return { type: 'user_left', } @@ -383,9 +377,7 @@ export function _messageActionFromTl( type: 'call', id: act.callId, isVideo: Boolean(act.video), - reason: act.reason ? - _callDiscardReasonFromTl(act.reason) : - undefined, + reason: act.reason ? _callDiscardReasonFromTl(act.reason) : undefined, duration: act.duration ?? 0, } case 'messageActionScreenshotTaken': diff --git a/packages/client/src/types/messages/message-entity.ts b/packages/client/src/types/messages/message-entity.ts index 8de31ed4..7957914b 100644 --- a/packages/client/src/types/messages/message-entity.ts +++ b/packages/client/src/types/messages/message-entity.ts @@ -2,9 +2,7 @@ import { tl } from '@mtcute/tl' import { makeInspectable } from '../utils' -const entityToType: Partial< - Record -> = { +const entityToType: Partial> = { messageEntityBlockquote: 'blockquote', messageEntityBold: 'bold', messageEntityBotCommand: 'bot_command', @@ -125,8 +123,7 @@ export class MessageEntity { offset: obj.offset, length: obj.length, url: obj._ === 'messageEntityTextUrl' ? obj.url : undefined, - userId: - obj._ === 'messageEntityMentionName' ? obj.userId : undefined, + userId: obj._ === 'messageEntityMentionName' ? obj.userId : undefined, language: obj._ === 'messageEntityPre' ? obj.language : undefined, emojiId: obj._ === 'messageEntityCustomEmoji' ? obj.documentId : undefined, } diff --git a/packages/client/src/types/messages/message-media.ts b/packages/client/src/types/messages/message-media.ts index 0db8e46b..effc3ad0 100644 --- a/packages/client/src/types/messages/message-media.ts +++ b/packages/client/src/types/messages/message-media.ts @@ -83,11 +83,7 @@ export function _messageMediaFromTl( if (!peers) { // should only be possible in extended media // (and afaik polls can't be there) - throw new MtTypeAssertionError( - "can't create poll without peers index", - 'PeersIndex', - 'null', - ) + throw new MtTypeAssertionError("can't create poll without peers index", 'PeersIndex', 'null') } return new Poll(client, m.poll, peers, m.results) diff --git a/packages/client/src/types/messages/message.ts b/packages/client/src/types/messages/message.ts index 8bd63933..88643b3e 100644 --- a/packages/client/src/types/messages/message.ts +++ b/packages/client/src/types/messages/message.ts @@ -1,10 +1,4 @@ -import { - assertNever, - getMarkedPeerId, - MtArgumentError, - MtTypeAssertionError, - toggleChannelIdMark, -} from '@mtcute/core' +import { assertNever, getMarkedPeerId, MtArgumentError, MtTypeAssertionError, toggleChannelIdMark } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' @@ -73,8 +67,7 @@ export interface MessageRepliesInfo { } /** Information about comments to a channel post */ -export interface MessageCommentsInfo - extends Omit { +export interface MessageCommentsInfo extends Omit { /** * Whether this is a comments thread under a channel post */ @@ -111,11 +104,7 @@ export class Message { readonly isScheduled = false, ) { if (raw._ === 'messageEmpty') { - throw new MtTypeAssertionError( - 'Message#ctor', - 'not messageEmpty', - 'messageEmpty', - ) + throw new MtTypeAssertionError('Message#ctor', 'not messageEmpty', 'messageEmpty') } this.raw = raw @@ -183,10 +172,7 @@ export class Message { if (!from) { if (this.raw.peerId._ === 'peerUser') { - this._sender = new User( - this.client, - this._peers.user(this.raw.peerId.userId), - ) + this._sender = new User(this.client, this._peers.user(this.raw.peerId.userId)) } else { // anon admin, return the chat this._sender = this.chat @@ -194,23 +180,13 @@ export class Message { } else { switch (from._) { case 'peerChannel': // forwarded channel post - this._sender = new Chat( - this.client, - this._peers.chat(from.channelId), - ) + this._sender = new Chat(this.client, this._peers.chat(from.channelId)) break case 'peerUser': - this._sender = new User( - this.client, - this._peers.user(from.userId), - ) + this._sender = new User(this.client, this._peers.user(from.userId)) break default: - throw new MtTypeAssertionError( - 'raw.fromId', - 'peerUser | peerChannel', - from._, - ) + throw new MtTypeAssertionError('raw.fromId', 'peerUser | peerChannel', from._) } } } @@ -225,11 +201,7 @@ export class Message { */ get chat(): Chat { if (this._chat === undefined) { - this._chat = Chat._parseFromMessage( - this.client, - this.raw, - this._peers, - ) + this._chat = Chat._parseFromMessage(this.client, this.raw, this._peers) } return this._chat @@ -261,23 +233,13 @@ export class Message { } else if (fwd.fromId) { switch (fwd.fromId._) { case 'peerChannel': - sender = new Chat( - this.client, - this._peers.chat(fwd.fromId.channelId), - ) + sender = new Chat(this.client, this._peers.chat(fwd.fromId.channelId)) break case 'peerUser': - sender = new User( - this.client, - this._peers.user(fwd.fromId.userId), - ) + sender = new User(this.client, this._peers.user(fwd.fromId.userId)) break default: - throw new MtTypeAssertionError( - 'raw.fwdFrom.fromId', - 'peerUser | peerChannel', - fwd.fromId._, - ) + throw new MtTypeAssertionError('raw.fwdFrom.fromId', 'peerUser | peerChannel', fwd.fromId._) } } else { this._forward = null @@ -317,8 +279,7 @@ export class Message { if (r.comments) { const o = obj as unknown as MessageCommentsInfo o.discussion = getMarkedPeerId(r.channelId!, 'channel') - o.repliers = - r.recentRepliers?.map((it) => getMarkedPeerId(it)) ?? [] + o.repliers = r.recentRepliers?.map((it) => getMarkedPeerId(it)) ?? [] } this._replies = obj @@ -364,10 +325,7 @@ export class Message { if (this.raw._ === 'messageService' || !this.raw.viaBotId) { this._viaBot = null } else { - this._viaBot = new User( - this.client, - this._peers.user(this.raw.viaBotId), - ) + this._viaBot = new User(this.client, this._peers.user(this.raw.viaBotId)) } } @@ -431,18 +389,10 @@ export class Message { */ get media(): MessageMedia { if (this._media === undefined) { - if ( - this.raw._ === 'messageService' || - !this.raw.media || - this.raw.media._ === 'messageMediaEmpty' - ) { + if (this.raw._ === 'messageService' || !this.raw.media || this.raw.media._ === 'messageMediaEmpty') { this._media = null } else { - this._media = _messageMediaFromTl( - this.client, - this._peers, - this.raw.media, - ) + this._media = _messageMediaFromTl(this.client, this._peers, this.raw.media) } } @@ -455,11 +405,7 @@ export class Message { * that was forwarded without author by a non-premium user */ get isForwardedPremiumMedia(): boolean { - return ( - this.raw._ === 'message' && - this.raw.media?._ === 'messageMediaDocument' && - this.raw.media.nopremium! - ) + return this.raw._ === 'message' && this.raw.media?._ === 'messageMediaDocument' && this.raw.media.nopremium! } private _markup?: ReplyMarkup | null @@ -548,22 +494,15 @@ export class Message { * @throws MtArgumentError In case the chat does not support message links */ get link(): string { - if ( - this.chat.chatType === 'supergroup' || - this.chat.chatType === 'channel' - ) { + if (this.chat.chatType === 'supergroup' || this.chat.chatType === 'channel') { if (this.chat.username) { return `https://t.me/${this.chat.username}/${this.id}` } - return `https://t.me/c/${toggleChannelIdMark(this.chat.id)}/${ - this.id - }` + return `https://t.me/c/${toggleChannelIdMark(this.chat.id)}/${this.id}` } - throw new MtArgumentError( - `Cannot generate message link for ${this.chat.chatType}`, - ) + throw new MtArgumentError(`Cannot generate message link for ${this.chat.chatType}`) } /** @@ -574,9 +513,7 @@ export class Message { * @param parseMode Parse mode to use (`null` for default) */ unparse(parseMode?: string | null): string { - return this.client - .getParseMode(parseMode) - .unparse(this.text, this.entities) + return this.client.getParseMode(parseMode).unparse(this.text, this.entities) } /** @@ -714,9 +651,7 @@ export class Message { } if (!this.replies || !this.replies.isComments) { - throw new MtArgumentError( - 'This message does not have comments section', - ) + throw new MtArgumentError('This message does not have comments section') } if (!params) params = {} @@ -747,9 +682,7 @@ export class Message { } if (!this.replies || !this.replies.isComments) { - throw new MtArgumentError( - 'This message does not have comments section', - ) + throw new MtArgumentError('This message does not have comments section') } if (!params) params = {} params.commentTo = this.id @@ -779,9 +712,7 @@ export class Message { } if (!this.replies || !this.replies.isComments) { - throw new MtArgumentError( - 'This message does not have comments section', - ) + throw new MtArgumentError('This message does not have comments section') } if (!params) params = {} params.commentTo = this.id @@ -805,12 +736,7 @@ export class Message { * @param bothSides Whether to pin for both sides (only for private chats) */ pin(notify = false, bothSides = false): Promise { - return this.client.pinMessage( - this.chat.inputPeer, - this.id, - notify, - bothSides, - ) + return this.client.pinMessage(this.chat.inputPeer, this.id, notify, bothSides) } /** @@ -825,9 +751,7 @@ export class Message { * * @link TelegramClient.editMessage */ - edit( - params: Parameters[2], - ): Promise { + edit(params: Parameters[2]): Promise { return this.client.editMessage(this.chat.inputPeer, this.id, params) } @@ -858,16 +782,8 @@ export class Message { * @param params * @returns Forwarded message */ - forwardTo( - peer: InputPeerLike, - params?: Parameters[3], - ): Promise { - return this.client.forwardMessages( - peer, - this.chat.inputPeer, - this.id, - params, - ) + forwardTo(peer: InputPeerLike, params?: Parameters[3]): Promise { + return this.client.forwardMessages(peer, this.chat.inputPeer, this.id, params) } /** @@ -882,10 +798,7 @@ export class Message { * @param toChatId Target chat ID * @param params Copy parameters */ - sendCopy( - toChatId: InputPeerLike, - params?: Parameters[3], - ): Promise { + sendCopy(toChatId: InputPeerLike, params?: Parameters[3]): Promise { if (!params) params = {} if (this.raw._ === 'messageService') { @@ -900,10 +813,7 @@ export class Message { file: this.media.inputMedia, caption: params.caption ?? this.raw.message, // we shouldn't use original entities if the user wants custom text - entities: - params.entities ?? params.caption ? - undefined : - this.raw.entities, + entities: params.entities ?? params.caption ? undefined : this.raw.entities, }, params, ) @@ -933,10 +843,7 @@ export class Message { * message. */ async getDiscussionMessage(): Promise { - return this.client.getDiscussionMessage( - this.chat.inputPeer, - this.raw.id, - ) + return this.client.getDiscussionMessage(this.chat.inputPeer, this.raw.id) } /** @@ -945,11 +852,7 @@ export class Message { * @param clearMentions Whether to also clear mentions */ async read(clearMentions = false): Promise { - return this.client.readHistory( - this.chat.inputPeer, - this.raw.id, - clearMentions, - ) + return this.client.readHistory(this.chat.inputPeer, this.raw.id, clearMentions) } /** @@ -959,12 +862,7 @@ export class Message { * @param big Whether to use a big reaction */ async react(emoji: string | null, big?: boolean): Promise { - return this.client.sendReaction( - this.chat.inputPeer, - this.raw.id, - emoji, - big, - ) + return this.client.sendReaction(this.chat.inputPeer, this.raw.id, emoji, big) } async getCustomEmojis(): Promise { diff --git a/packages/client/src/types/messages/reactions.ts b/packages/client/src/types/messages/reactions.ts index 9c26fc5e..c80c91bb 100644 --- a/packages/client/src/types/messages/reactions.ts +++ b/packages/client/src/types/messages/reactions.ts @@ -66,10 +66,7 @@ export class PeerReaction { if (!this._user) { assertTypeIs('PeerReaction#user', this.raw.peerId, 'peerUser') - this._user = new User( - this.client, - this._peers.user(this.raw.peerId.userId), - ) + this._user = new User(this.client, this._peers.user(this.raw.peerId.userId)) } return this._user @@ -122,9 +119,7 @@ export class MessageReactions { /** * Get the users who reacted to this message */ - getUsers( - params?: Parameters[2], - ): AsyncIterableIterator { + getUsers(params?: Parameters[2]): AsyncIterableIterator { return this.client.getReactionUsers(this.messageId, this.chatId, params) } } diff --git a/packages/client/src/types/misc/sticker-set.ts b/packages/client/src/types/misc/sticker-set.ts index 2da60173..606b1c00 100644 --- a/packages/client/src/types/misc/sticker-set.ts +++ b/packages/client/src/types/misc/sticker-set.ts @@ -5,13 +5,7 @@ import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' import { MtEmptyError } from '../errors' import { InputFileLike } from '../files' -import { - MaskPosition, - Sticker, - StickerSourceType, - StickerType, - Thumbnail, -} from '../media' +import { MaskPosition, Sticker, StickerSourceType, StickerType, Thumbnail } from '../media' import { parseDocument } from '../media/document-utils' import { makeInspectable } from '../utils' @@ -47,21 +41,14 @@ export class StickerSet { */ readonly isFull: boolean - constructor( - readonly client: TelegramClient, - raw: tl.TypeStickerSet | tl.messages.TypeStickerSet, - ) { + constructor(readonly client: TelegramClient, raw: tl.TypeStickerSet | tl.messages.TypeStickerSet) { if (raw._ === 'messages.stickerSet') { this.full = raw this.brief = raw.set } else if (raw._ === 'stickerSet') { this.brief = raw } else { - throw new MtTypeAssertionError( - 'StickerSet', - 'messages.stickerSet | stickerSet', - raw._, - ) + throw new MtTypeAssertionError('StickerSet', 'messages.stickerSet | stickerSet', raw._) } this.isFull = raw._ === 'messages.stickerSet' @@ -116,9 +103,7 @@ export class StickerSet { * Date when this sticker set was installed */ get installedDate(): Date | null { - return this.brief.installedDate ? - new Date(this.brief.installedDate * 1000) : - null + return this.brief.installedDate ? new Date(this.brief.installedDate * 1000) : null } /** @@ -169,17 +154,10 @@ export class StickerSet { const index = new LongMap>() this.full!.documents.forEach((doc) => { - const sticker = parseDocument( - this.client, - doc as tl.RawDocument, - ) + const sticker = parseDocument(this.client, doc as tl.RawDocument) if (!(sticker instanceof Sticker)) { - throw new MtTypeAssertionError( - 'full.documents', - 'Sticker', - sticker.mimeType, - ) + throw new MtTypeAssertionError('full.documents', 'Sticker', sticker.mimeType) } const info: tl.Mutable = { @@ -213,10 +191,7 @@ export class StickerSet { * (i.e. first sticker should be used as thumbnail) */ get thumbnails(): ReadonlyArray { - return (this._thumbnails ??= - this.brief.thumbs?.map( - (sz) => new Thumbnail(this.client, this.brief, sz), - ) ?? []) + return (this._thumbnails ??= this.brief.thumbs?.map((sz) => new Thumbnail(this.client, this.brief, sz)) ?? []) } /** @@ -240,9 +215,7 @@ export class StickerSet { * In case this object does not contain info about stickers (i.e. {@link isFull} = false) */ getStickersByEmoji(emoji: string): StickerInfo[] { - return this.stickers.filter( - (it) => it.alt === emoji || it.emoji.includes(emoji), - ) + return this.stickers.filter((it) => it.alt === emoji || it.emoji.includes(emoji)) } /** @@ -301,9 +274,7 @@ export class StickerSet { * Sticker File ID. In case this is a full sticker set object, * you can also pass index (even negative), and that sticker will be removed */ - async deleteSticker( - sticker: number | Parameters[0], - ): Promise { + async deleteSticker(sticker: number | Parameters[0]): Promise { if (typeof sticker === 'number') { sticker = this._getInputDocument(sticker) } @@ -350,9 +321,7 @@ export class StickerSet { * you can also pass index (even negative), and that sticker * will be used as a thumb */ - async setThumb( - thumb: number | Parameters[1], - ): Promise { + async setThumb(thumb: number | Parameters[1]): Promise { if (typeof thumb === 'number') { thumb = this._getInputDocument(thumb) } diff --git a/packages/client/src/types/misc/takeout-session.ts b/packages/client/src/types/misc/takeout-session.ts index 275218bc..5a672326 100644 --- a/packages/client/src/types/misc/takeout-session.ts +++ b/packages/client/src/types/misc/takeout-session.ts @@ -13,10 +13,7 @@ export class TakeoutSession { */ readonly id: tl.Long - constructor( - readonly client: TelegramClient, - session: tl.account.RawTakeout, - ) { + constructor(readonly client: TelegramClient, session: tl.account.RawTakeout) { this.id = session.id } diff --git a/packages/client/src/types/peers/chat-event.ts b/packages/client/src/types/peers/chat-event.ts index 646ab7a9..262d5a71 100644 --- a/packages/client/src/types/peers/chat-event.ts +++ b/packages/client/src/types/peers/chat-event.ts @@ -322,10 +322,7 @@ export type ChatAction = | ChatActionTtlChanged | null -function _actionFromTl( - this: ChatEvent, - e: tl.TypeChannelAdminLogEventAction, -): ChatAction { +function _actionFromTl(this: ChatEvent, e: tl.TypeChannelAdminLogEventAction): ChatAction { switch (e._) { case 'channelAdminLogEventActionParticipantJoin': return { type: 'user_joined' } @@ -391,21 +388,13 @@ function _actionFromTl( case 'channelAdminLogEventActionParticipantToggleBan': return { type: 'user_perms_changed', - old: new ChatMember( - this.client, - e.prevParticipant, - this._peers, - ), + old: new ChatMember(this.client, e.prevParticipant, this._peers), new: new ChatMember(this.client, e.newParticipant, this._peers), } case 'channelAdminLogEventActionParticipantToggleAdmin': return { type: 'user_admin_perms_changed', - old: new ChatMember( - this.client, - e.prevParticipant, - this._peers, - ), + old: new ChatMember(this.client, e.prevParticipant, this._peers), new: new ChatMember(this.client, e.newParticipant, this._peers), } case 'channelAdminLogEventActionChangeStickerSet': @@ -440,14 +429,8 @@ function _actionFromTl( case 'channelAdminLogEventActionChangeLocation': return { type: 'location_changed', - old: - e.prevValue._ === 'channelLocationEmpty' ? - null : - new ChatLocation(this.client, e.prevValue), - new: - e.newValue._ === 'channelLocationEmpty' ? - null : - new ChatLocation(this.client, e.newValue), + old: e.prevValue._ === 'channelLocationEmpty' ? null : new ChatLocation(this.client, e.prevValue), + new: e.newValue._ === 'channelLocationEmpty' ? null : new ChatLocation(this.client, e.newValue), } case 'channelAdminLogEventActionToggleSlowMode': return { @@ -536,10 +519,7 @@ export class ChatEvent { * Actor of the event */ get actor(): User { - return (this._actor ??= new User( - this.client, - this._peers.user(this.raw.userId), - )) + return (this._actor ??= new User(this.client, this._peers.user(this.raw.userId))) } private _action?: ChatAction diff --git a/packages/client/src/types/peers/chat-invite-link.ts b/packages/client/src/types/peers/chat-invite-link.ts index 8b001b93..d203eb27 100644 --- a/packages/client/src/types/peers/chat-invite-link.ts +++ b/packages/client/src/types/peers/chat-invite-link.ts @@ -38,17 +38,9 @@ export interface ChatInviteLinkJoinedMember { export class ChatInviteLink { raw: tl.RawChatInviteExported - constructor( - readonly client: TelegramClient, - raw: tl.TypeExportedChatInvite, - readonly _peers?: PeersIndex, - ) { + constructor(readonly client: TelegramClient, raw: tl.TypeExportedChatInvite, readonly _peers?: PeersIndex) { if (raw._ === 'chatInvitePublicJoinRequests') { - throw new MtTypeAssertionError( - 'ChatInviteLink', - 'chatInviteExported', - raw._, - ) + throw new MtTypeAssertionError('ChatInviteLink', 'chatInviteExported', raw._) } this.raw = raw } @@ -81,10 +73,7 @@ export class ChatInviteLink { get creator(): User | null { if (!this._peers) return null - return (this._creator ??= new User( - this.client, - this._peers.user(this.raw.adminId), - )) + return (this._creator ??= new User(this.client, this._peers.user(this.raw.adminId))) } /** diff --git a/packages/client/src/types/peers/chat-location.ts b/packages/client/src/types/peers/chat-location.ts index fe6798ce..ec788a7f 100644 --- a/packages/client/src/types/peers/chat-location.ts +++ b/packages/client/src/types/peers/chat-location.ts @@ -8,20 +8,14 @@ import { makeInspectable } from '../utils' * Geolocation of a supergroup */ export class ChatLocation { - constructor( - readonly client: TelegramClient, - readonly raw: tl.RawChannelLocation, - ) {} + constructor(readonly client: TelegramClient, readonly raw: tl.RawChannelLocation) {} private _location?: Location /** * Location of the chat */ get location(): Location { - return (this._location ??= new Location( - this.client, - this.raw.geoPoint as tl.RawGeoPoint, - )) + return (this._location ??= new Location(this.client, this.raw.geoPoint as tl.RawGeoPoint)) } /** diff --git a/packages/client/src/types/peers/chat-member.ts b/packages/client/src/types/peers/chat-member.ts index fba0f371..2b82a0d4 100644 --- a/packages/client/src/types/peers/chat-member.ts +++ b/packages/client/src/types/peers/chat-member.ts @@ -16,13 +16,7 @@ import { User } from './user' * - `banned`: user was banned from the chat * - `left`: user left the chat on their own */ -export type ChatMemberStatus = - | 'creator' - | 'admin' - | 'member' - | 'restricted' - | 'banned' - | 'left' +export type ChatMemberStatus = 'creator' | 'admin' | 'member' | 'restricted' | 'banned' | 'left' /** * Information about one chat member @@ -43,22 +37,12 @@ export class ChatMember { switch (this.raw._) { case 'channelParticipantBanned': case 'channelParticipantLeft': - assertTypeIs( - 'ChatMember#user (raw.peer)', - this.raw.peer, - 'peerUser', - ) + assertTypeIs('ChatMember#user (raw.peer)', this.raw.peer, 'peerUser') - this._user = new User( - this.client, - this._peers.user(this.raw.peer.userId), - ) + this._user = new User(this.client, this._peers.user(this.raw.peer.userId)) break default: - this._user = new User( - this.client, - this._peers.user(this.raw.userId), - ) + this._user = new User(this.client, this._peers.user(this.raw.userId)) break } } @@ -84,9 +68,7 @@ export class ChatMember { case 'channelParticipantLeft': return 'left' case 'channelParticipantBanned': - return this.raw.bannedRights.viewMessages ? - 'banned' : - 'restricted' + return this.raw.bannedRights.viewMessages ? 'banned' : 'restricted' } // fallback @@ -136,10 +118,7 @@ export class ChatMember { get invitedBy(): User | null { if (this._invitedBy === undefined) { if ('inviterId' in this.raw && this.raw.inviterId) { - this._invitedBy = new User( - this.client, - this._peers.user(this.raw.inviterId), - ) + this._invitedBy = new User(this.client, this._peers.user(this.raw.inviterId)) } else { this._invitedBy = null } @@ -157,10 +136,7 @@ export class ChatMember { get promotedBy(): User | null { if (this._promotedBy === undefined) { if (this.raw._ === 'channelParticipantAdmin') { - this._promotedBy = new User( - this.client, - this._peers.user(this.raw.promotedBy), - ) + this._promotedBy = new User(this.client, this._peers.user(this.raw.promotedBy)) } else { this._promotedBy = null } @@ -178,10 +154,7 @@ export class ChatMember { get restrictedBy(): User | null { if (this._restrictedBy === undefined) { if (this.raw._ === 'channelParticipantBanned') { - this._restrictedBy = new User( - this.client, - this._peers.user(this.raw.kickedBy), - ) + this._restrictedBy = new User(this.client, this._peers.user(this.raw.kickedBy)) } else { this._restrictedBy = null } @@ -198,9 +171,7 @@ export class ChatMember { get restrictions(): ChatPermissions | null { if (this.raw._ !== 'channelParticipantBanned') return null - return (this._restrictions ??= new ChatPermissions( - this.raw.bannedRights, - )) + return (this._restrictions ??= new ChatPermissions(this.raw.bannedRights)) } /** @@ -209,9 +180,7 @@ export class ChatMember { * Makes sense only when `status = restricted or staus = banned` */ get isMember(): boolean { - return this.raw._ === 'channelParticipantBanned' ? - !this.raw.left : - this.raw._ !== 'channelParticipantLeft' + return this.raw._ === 'channelParticipantBanned' ? !this.raw.left : this.raw._ !== 'channelParticipantLeft' } /** diff --git a/packages/client/src/types/peers/chat-permissions.ts b/packages/client/src/types/peers/chat-permissions.ts index deadb377..4d09349d 100644 --- a/packages/client/src/types/peers/chat-permissions.ts +++ b/packages/client/src/types/peers/chat-permissions.ts @@ -121,9 +121,7 @@ export class ChatPermissions { * will be lifted from a {@link ChatMember} */ get untilDate(): Date | null { - return this.raw.untilDate === 0 ? - null : - new Date(this.raw.untilDate * 1000) + return this.raw.untilDate === 0 ? null : new Date(this.raw.untilDate * 1000) } } diff --git a/packages/client/src/types/peers/chat-photo.ts b/packages/client/src/types/peers/chat-photo.ts index a5ef509c..3e0a248e 100644 --- a/packages/client/src/types/peers/chat-photo.ts +++ b/packages/client/src/types/peers/chat-photo.ts @@ -92,20 +92,17 @@ export class ChatPhotoSize extends FileLocation { * TDLib and Bot API compatible unique File ID representing this size */ get uniqueFileId(): string { - return (this._uniqueFileId ??= toUniqueFileId( - tdFileId.FileType.ProfilePhoto, - { - _: 'photo', - id: this.obj.photoId, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - source: { - _: 'dialogPhoto', - big: this.big, - // will be looked into in MTQ-37 - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as any, - }, - )) + return (this._uniqueFileId ??= toUniqueFileId(tdFileId.FileType.ProfilePhoto, { + _: 'photo', + id: this.obj.photoId, + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + source: { + _: 'dialogPhoto', + big: this.big, + // will be looked into in MTQ-37 + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any, + })) } } @@ -132,24 +129,14 @@ export class ChatPhoto { /** Chat photo file location in small resolution (160x160) */ get small(): ChatPhotoSize { - return (this._smallFile ??= new ChatPhotoSize( - this.client, - this.peer, - this.raw, - false, - )) + return (this._smallFile ??= new ChatPhotoSize(this.client, this.peer, this.raw, false)) } private _bigFile?: ChatPhotoSize /** Chat photo file location in big resolution (640x640) */ get big(): ChatPhotoSize { - return (this._bigFile ??= new ChatPhotoSize( - this.client, - this.peer, - this.raw, - true, - )) + return (this._bigFile ??= new ChatPhotoSize(this.client, this.peer, this.raw, true)) } private _thumb?: Buffer diff --git a/packages/client/src/types/peers/chat.ts b/packages/client/src/types/peers/chat.ts index 4f3d766d..6c3856f8 100644 --- a/packages/client/src/types/peers/chat.ts +++ b/packages/client/src/types/peers/chat.ts @@ -1,9 +1,4 @@ -import { - getMarkedPeerId, - MaybeArray, - MtArgumentError, - MtTypeAssertionError, -} from '@mtcute/core' +import { getMarkedPeerId, MaybeArray, MtArgumentError, MtTypeAssertionError } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' @@ -24,13 +19,7 @@ import { InputPeerLike, PeersIndex, User } from './index' * - `channel`: Broadcast channel * - `gigagroup`: Gigagroup aka Broadcast group */ -export type ChatType = - | 'private' - | 'bot' - | 'group' - | 'supergroup' - | 'channel' - | 'gigagroup' +export type ChatType = 'private' | 'bot' | 'group' | 'supergroup' | 'channel' | 'gigagroup' /** * A chat. @@ -41,12 +30,7 @@ export class Chat { /** * Raw peer object that this {@link Chat} represents. */ - readonly peer: - | tl.RawUser - | tl.RawChat - | tl.RawChannel - | tl.RawChatForbidden - | tl.RawChannelForbidden + readonly peer: tl.RawUser | tl.RawChat | tl.RawChannel | tl.RawChatForbidden | tl.RawChannelForbidden constructor( readonly client: TelegramClient, @@ -63,11 +47,7 @@ export class Chat { case 'channelForbidden': break default: - throw new MtTypeAssertionError( - 'peer', - 'user | chat | channel', - peer._, - ) + throw new MtTypeAssertionError('peer', 'user | chat | channel', peer._) } this.client = client @@ -89,9 +69,7 @@ export class Chat { switch (this.peer._) { case 'user': if (!this.peer.accessHash) { - throw new MtArgumentError( - "Peer's access hash is not available!", - ) + throw new MtArgumentError("Peer's access hash is not available!") } this._inputPeer = { @@ -110,9 +88,7 @@ export class Chat { case 'channel': case 'channelForbidden': if (!this.peer.accessHash) { - throw new MtArgumentError( - "Peer's access hash is not available!", - ) + throw new MtArgumentError("Peer's access hash is not available!") } this._inputPeer = { @@ -283,17 +259,12 @@ export class Chat { if ( !('photo' in this.peer) || !this.peer.photo || - (this.peer.photo._ !== 'userProfilePhoto' && - this.peer.photo._ !== 'chatPhoto') + (this.peer.photo._ !== 'userProfilePhoto' && this.peer.photo._ !== 'chatPhoto') ) { return null } - return (this._photo ??= new ChatPhoto( - this.client, - this.inputPeer, - this.peer.photo, - )) + return (this._photo ??= new ChatPhoto(this.client, this.inputPeer, this.peer.photo)) } /** @@ -319,12 +290,8 @@ export class Chat { if (!('photo' in this.peer)) return null return ( - ( - this.peer.photo as Exclude< - typeof this.peer.photo, - tl.RawChatPhotoEmpty | tl.RawUserProfilePhotoEmpty - > - )?.dcId ?? null + (this.peer.photo as Exclude) + ?.dcId ?? null ) } @@ -350,9 +317,7 @@ export class Chat { * Returned only in {@link TelegramClient.getFullChat} */ get stickerSetName(): string | null { - return this.fullPeer && this.fullPeer._ === 'channelFull' ? - this.fullPeer.stickerset?.shortName ?? null : - null + return this.fullPeer && this.fullPeer._ === 'channelFull' ? this.fullPeer.stickerset?.shortName ?? null : null } /** @@ -360,9 +325,7 @@ export class Chat { * Returned only in {@link TelegramClient.getFullChat} */ get canSetStickerSet(): boolean | null { - return this.fullPeer && this.fullPeer._ === 'channelFull' ? - this.fullPeer.canSetStickers ?? null : - null + return this.fullPeer && this.fullPeer._ === 'channelFull' ? this.fullPeer.canSetStickers ?? null : null } /** @@ -381,10 +344,7 @@ export class Chat { // null if (this.fullPeer && this.fullPeer._ !== 'userFull') { - if ( - this.fullPeer._ === 'chatFull' && - this.fullPeer.participants._ === 'chatParticipants' - ) { + if (this.fullPeer._ === 'chatFull' && this.fullPeer.participants._ === 'chatParticipants') { return this.fullPeer.participants.participants.length } else if (this.fullPeer._ === 'channelFull') { return this.fullPeer.participantsCount ?? null @@ -399,9 +359,7 @@ export class Chat { * This field is available only in case {@link isRestricted} is `true` */ get restrictions(): ReadonlyArray | null { - return 'restrictionReason' in this.peer ? - this.peer.restrictionReason ?? null : - null + return 'restrictionReason' in this.peer ? this.peer.restrictionReason ?? null : null } private _permissions?: ChatPermissions @@ -414,25 +372,18 @@ export class Chat { return null } - return (this._permissions ??= new ChatPermissions( - this.peer.bannedRights, - )) + return (this._permissions ??= new ChatPermissions(this.peer.bannedRights)) } /** * Default chat member permissions, for groups and supergroups. */ get defaultPermissions(): ChatPermissions | null { - if ( - !('defaultBannedRights' in this.peer) || - !this.peer.defaultBannedRights - ) { + if (!('defaultBannedRights' in this.peer) || !this.peer.defaultBannedRights) { return null } - return (this._permissions ??= new ChatPermissions( - this.peer.defaultBannedRights, - )) + return (this._permissions ??= new ChatPermissions(this.peer.defaultBannedRights)) } /** @@ -455,18 +406,11 @@ export class Chat { * Returned only in {@link TelegramClient.getFullChat} */ get location(): ChatLocation | null { - if ( - !this.fullPeer || - this.fullPeer._ !== 'channelFull' || - this.fullPeer.location?._ !== 'channelLocation' - ) { + if (!this.fullPeer || this.fullPeer._ !== 'channelFull' || this.fullPeer.location?._ !== 'channelLocation') { return null } - return (this._location ??= new ChatLocation( - this.client, - this.fullPeer.location, - )) + return (this._location ??= new ChatLocation(this.client, this.fullPeer.location)) } private _linkedChat?: Chat @@ -502,11 +446,7 @@ export class Chat { } /** @internal */ - static _parseFromPeer( - client: TelegramClient, - peer: tl.TypePeer, - peers: PeersIndex, - ): Chat { + static _parseFromPeer(client: TelegramClient, peer: tl.TypePeer, peers: PeersIndex): Chat { switch (peer._) { case 'peerUser': return new Chat(client, peers.user(peer.userId)) @@ -518,19 +458,12 @@ export class Chat { } /** @internal */ - static _parseFull( - client: TelegramClient, - full: tl.messages.RawChatFull | tl.users.TypeUserFull, - ): Chat { + static _parseFull(client: TelegramClient, full: tl.messages.RawChatFull | tl.users.TypeUserFull): Chat { if (full._ === 'users.userFull') { const user = full.users.find((it) => it.id === full.fullUser.id) if (!user || user._ === 'userEmpty') { - throw new MtTypeAssertionError( - 'Chat._parseFull', - 'user', - user?._ ?? 'undefined', - ) + throw new MtTypeAssertionError('Chat._parseFull', 'user', user?._ ?? 'undefined') } return new Chat(client, user, full.fullUser) @@ -544,10 +477,7 @@ export class Chat { if (fullChat.id === c.id) { chat = c } - if ( - fullChat._ === 'channelFull' && - fullChat.linkedChatId === c.id - ) { + if (fullChat._ === 'channelFull' && fullChat.linkedChatId === c.id) { linked = c } } @@ -579,10 +509,7 @@ export class Chat { * msg.replyText(`Hello, ${msg.chat.mention()`) * ``` */ - mention( - text?: string | null, - parseMode?: T | null, - ): string | FormattedString { + mention(text?: string | null, parseMode?: T | null): string | FormattedString { if (this.user) return this.user.mention(text, parseMode) if (text === undefined && this.username) { @@ -625,10 +552,7 @@ export class Chat { * Number of old messages to be forwarded (0-100). * Only applicable to legacy groups, ignored for supergroups and channels */ - async addMembers( - users: MaybeArray, - forwardCount?: number, - ): Promise { + async addMembers(users: MaybeArray, forwardCount?: number): Promise { return this.client.addChatMembers(this.inputPeer, users, forwardCount) } diff --git a/packages/client/src/types/peers/index.ts b/packages/client/src/types/peers/index.ts index dec23efa..880c63e0 100644 --- a/packages/client/src/types/peers/index.ts +++ b/packages/client/src/types/peers/index.ts @@ -35,10 +35,4 @@ export type PeerType = 'user' | 'bot' | 'group' | 'channel' | 'supergroup' * > Telegram has moved to int64 IDs. Though, Levin [has confirmed](https://t.me/tdlibchat/25075) * > that new IDs *will* still fit into int53, meaning JS integers are fine. */ -export type InputPeerLike = - | string - | number - | tl.TypePeer - | tl.TypeInputPeer - | tl.TypeInputUser - | tl.TypeInputChannel +export type InputPeerLike = string | number | tl.TypePeer | tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel diff --git a/packages/client/src/types/peers/peers-index.ts b/packages/client/src/types/peers/peers-index.ts index 84b78996..086364cd 100644 --- a/packages/client/src/types/peers/peers-index.ts +++ b/packages/client/src/types/peers/peers-index.ts @@ -1,8 +1,7 @@ import { MtArgumentError } from '@mtcute/core' import { tl } from '@mtcute/tl' -const ERROR_MSG = - 'Given peer is not available in this index. This is most likely an internal library error.' +const ERROR_MSG = 'Given peer is not available in this index. This is most likely an internal library error.' export class PeersIndex { readonly users: Map = new Map() @@ -10,10 +9,7 @@ export class PeersIndex { hasMin = false - static from(obj: { - users?: tl.TypeUser[] - chats?: tl.TypeChat[] - }): PeersIndex { + static from(obj: { users?: tl.TypeUser[]; chats?: tl.TypeChat[] }): PeersIndex { const index = new PeersIndex() obj.users?.forEach((user) => { @@ -30,10 +26,7 @@ export class PeersIndex { ( chat as Exclude< typeof chat, - | tl.RawChatEmpty - | tl.RawChat - | tl.RawChatForbidden - | tl.RawChannelForbidden + tl.RawChatEmpty | tl.RawChat | tl.RawChatForbidden | tl.RawChannelForbidden > ).min ) { diff --git a/packages/client/src/types/peers/user.ts b/packages/client/src/types/peers/user.ts index 3df1c852..47abfe02 100644 --- a/packages/client/src/types/peers/user.ts +++ b/packages/client/src/types/peers/user.ts @@ -19,14 +19,7 @@ import { ChatPhoto } from './chat-photo' * - `long_time_ago`, blocked user or user with hidden last seen time who was online more than a month ago. * - `bot`, for bots. */ -export type UserStatus = - | 'online' - | 'offline' - | 'recently' - | 'within_week' - | 'within_month' - | 'long_time_ago' - | 'bot' +export type UserStatus = 'online' | 'offline' | 'recently' | 'within_week' | 'within_month' | 'long_time_ago' | 'bot' export interface UserParsedStatus { status: UserStatus @@ -128,10 +121,7 @@ export class User { return this.raw.lastName ?? null } - static parseStatus( - status: tl.TypeUserStatus, - bot = false, - ): UserParsedStatus { + static parseStatus(status: tl.TypeUserStatus, bot = false): UserParsedStatus { let ret: UserStatus let date: Date @@ -227,14 +217,7 @@ export class User { * More info at [Pyrogram FAQ](https://docs.pyrogram.org/faq#what-are-the-ip-addresses-of-telegram-data-centers). */ get dcId(): number | null { - return ( - ( - this.raw.photo as Exclude< - typeof this.raw.photo, - tl.RawUserProfilePhotoEmpty - > - )?.dcId ?? null - ) + return (this.raw.photo as Exclude)?.dcId ?? null } /** User's phone number */ @@ -265,11 +248,7 @@ export class User { get photo(): ChatPhoto | null { if (this.raw.photo?._ !== 'userProfilePhoto') return null - return (this._photo ??= new ChatPhoto( - this.client, - this.inputPeer, - this.raw.photo, - )) + return (this._photo ??= new ChatPhoto(this.client, this.inputPeer, this.raw.photo)) } /** @@ -309,10 +288,7 @@ export class User { * msg.replyText(`Hello, ${msg.sender.mention()`) * ``` */ - mention( - text?: string | null, - parseMode?: T | null, - ): string | FormattedString { + mention(text?: string | null, parseMode?: T | null): string | FormattedString { if (text === undefined && this.username) { return `@${this.username}` } @@ -366,10 +342,7 @@ export class User { * @param text Mention text * @param parseMode Parse mode to use when creating mention */ - permanentMention( - text?: string | null, - parseMode?: T | null, - ): FormattedString { + permanentMention(text?: string | null, parseMode?: T | null): FormattedString { if (!this.raw.accessHash) { throw new MtArgumentError("user's access hash is not available!") } @@ -388,9 +361,7 @@ export class User { type: 'text_link', offset: 0, length: text.length, - url: `tg://user?id=${ - this.id - }&hash=${this.raw.accessHash.toString(16)}`, + url: `tg://user?id=${this.id}&hash=${this.raw.accessHash.toString(16)}`, }, ]), parseMode, diff --git a/packages/client/src/types/updates/bot-chat-join-request.ts b/packages/client/src/types/updates/bot-chat-join-request.ts index 39b57289..2710cc4a 100644 --- a/packages/client/src/types/updates/bot-chat-join-request.ts +++ b/packages/client/src/types/updates/bot-chat-join-request.ts @@ -31,10 +31,7 @@ export class BotChatJoinRequestUpdate { * Object containing the chat information. */ get chat(): Chat { - return (this._chat ??= new Chat( - this.client, - this._peers.chat(getBarePeerId(this.raw.peer)), - )) + return (this._chat ??= new Chat(this.client, this._peers.chat(getBarePeerId(this.raw.peer)))) } /** @@ -49,10 +46,7 @@ export class BotChatJoinRequestUpdate { * Object containing the user information. */ get user(): User { - return (this._user ??= new User( - this.client, - this._peers.user(this.raw.userId), - )) + return (this._user ??= new User(this.client, this._peers.user(this.raw.userId))) } /** @@ -75,23 +69,14 @@ export class BotChatJoinRequestUpdate { * Invite link used to request joining. */ get invite(): ChatInviteLink { - return (this._invite ??= new ChatInviteLink( - this.client, - this.raw.invite, - )) + return (this._invite ??= new ChatInviteLink(this.client, this.raw.invite)) } /** * Approve or deny the request. */ - hide( - action: Parameters[2], - ): Promise { - return this.client.hideJoinRequest( - this.chat.inputPeer, - this.user.inputPeer, - action, - ) + hide(action: Parameters[2]): Promise { + return this.client.hideJoinRequest(this.chat.inputPeer, this.user.inputPeer, action) } } diff --git a/packages/client/src/types/updates/bot-stopped.ts b/packages/client/src/types/updates/bot-stopped.ts index e701dfae..ad0917a7 100644 --- a/packages/client/src/types/updates/bot-stopped.ts +++ b/packages/client/src/types/updates/bot-stopped.ts @@ -11,11 +11,7 @@ import { makeInspectable } from '../utils' * interacts with the bot. */ export class BotStoppedUpdate { - constructor( - readonly client: TelegramClient, - readonly raw: tl.RawUpdateBotStopped, - readonly _peers: PeersIndex, - ) {} + constructor(readonly client: TelegramClient, readonly raw: tl.RawUpdateBotStopped, readonly _peers: PeersIndex) {} /** * ID of the user who stopped or restarted the bot @@ -30,10 +26,7 @@ export class BotStoppedUpdate { * User who stopped or restarted the bot */ get user(): User { - return (this._user ??= new User( - this.client, - this._peers.user(this.raw.userId), - )) + return (this._user ??= new User(this.client, this._peers.user(this.raw.userId))) } /** diff --git a/packages/client/src/types/updates/chat-join-request.ts b/packages/client/src/types/updates/chat-join-request.ts index 7b413f6e..86a4098f 100644 --- a/packages/client/src/types/updates/chat-join-request.ts +++ b/packages/client/src/types/updates/chat-join-request.ts @@ -56,23 +56,15 @@ export class ChatJoinRequestUpdate { /** * Approve or deny the last requested user */ - hideLast( - action: Parameters[2], - ): Promise { - return this.client.hideJoinRequest( - this.chatId, - this.raw.recentRequesters[0], - action, - ) + hideLast(action: Parameters[2]): Promise { + return this.client.hideJoinRequest(this.chatId, this.raw.recentRequesters[0], action) } /** * Approve or deny all recent requests * (the ones available in {@link recentRequesters}) */ - async hideAllRecent( - action: Parameters[2], - ): Promise { + async hideAllRecent(action: Parameters[2]): Promise { for (const id of this.raw.recentRequesters) { await this.client.hideJoinRequest(this.chatId, id, action) } @@ -81,10 +73,7 @@ export class ChatJoinRequestUpdate { /** * Fetch all pending join requests for this chat */ - fetchAll(params?: { - limit?: number - search?: string - }): AsyncIterableIterator { + fetchAll(params?: { limit?: number; search?: string }): AsyncIterableIterator { return this.client.getInviteLinkMembers(this.chatId, { limit: params?.limit, requested: true, diff --git a/packages/client/src/types/updates/chat-member-update.ts b/packages/client/src/types/updates/chat-member-update.ts index fd434b54..aba9714e 100644 --- a/packages/client/src/types/updates/chat-member-update.ts +++ b/packages/client/src/types/updates/chat-member-update.ts @@ -37,9 +37,7 @@ export type ChatMemberUpdateType = | 'new_owner' | 'other' -function extractPeerId( - raw?: tl.TypeChatParticipant | tl.TypeChannelParticipant, -) { +function extractPeerId(raw?: tl.TypeChatParticipant | tl.TypeChannelParticipant) { if (!raw) return 0 if (tl.isAnyChatParticipant(raw)) { @@ -64,9 +62,7 @@ function extractPeerId( export class ChatMemberUpdate { constructor( readonly client: TelegramClient, - readonly raw: - | tl.RawUpdateChatParticipant - | tl.RawUpdateChannelParticipant, + readonly raw: tl.RawUpdateChatParticipant | tl.RawUpdateChannelParticipant, readonly _peers: PeersIndex, ) {} @@ -151,17 +147,11 @@ export class ChatMemberUpdate { return (this._type = 'new_owner') } - if ( - old._ === 'channelParticipantBanned' && - cur._ === 'channelParticipant' - ) { + if (old._ === 'channelParticipantBanned' && cur._ === 'channelParticipant') { return (this._type = 'unrestricted') } - if ( - old._ === 'channelParticipantAdmin' && - cur._ === 'channelParticipant' - ) { + if (old._ === 'channelParticipantAdmin' && cur._ === 'channelParticipant') { return (this._type = 'demoted') } @@ -177,10 +167,7 @@ export class ChatMemberUpdate { */ get chat(): Chat { if (!this._chat) { - const id = - this.raw._ === 'updateChannelParticipant' ? - this.raw.channelId : - this.raw.chatId + const id = this.raw._ === 'updateChannelParticipant' ? this.raw.channelId : this.raw.chatId this._chat = new Chat(this.client, this._peers.chat(id)) } @@ -194,10 +181,7 @@ export class ChatMemberUpdate { * Can be chat/channel administrator or the {@link user} themself. */ get actor(): User { - return (this._actor ??= new User( - this.client, - this._peers.user(this.raw.actorId), - )) + return (this._actor ??= new User(this.client, this._peers.user(this.raw.actorId))) } private _user?: User @@ -205,10 +189,7 @@ export class ChatMemberUpdate { * User representing the chat member whose status was changed. */ get user(): User { - return (this._user ??= new User( - this.client, - this._peers.user(this.raw.userId), - )) + return (this._user ??= new User(this.client, this._peers.user(this.raw.userId))) } private _oldMember?: ChatMember @@ -218,11 +199,7 @@ export class ChatMemberUpdate { get oldMember(): ChatMember | null { if (!this.raw.prevParticipant) return null - return (this._oldMember ??= new ChatMember( - this.client, - this.raw.prevParticipant, - this._peers, - )) + return (this._oldMember ??= new ChatMember(this.client, this.raw.prevParticipant, this._peers)) } private _newMember?: ChatMember @@ -232,11 +209,7 @@ export class ChatMemberUpdate { get newMember(): ChatMember | null { if (!this.raw.newParticipant) return null - return (this._newMember ??= new ChatMember( - this.client, - this.raw.newParticipant, - this._peers, - )) + return (this._newMember ??= new ChatMember(this.client, this.raw.newParticipant, this._peers)) } private _inviteLink?: ChatInviteLink @@ -246,10 +219,7 @@ export class ChatMemberUpdate { get inviteLink(): ChatInviteLink | null { if (!this.raw.invite) return null - return (this._inviteLink ??= new ChatInviteLink( - this.client, - this.raw.invite, - )) + return (this._inviteLink ??= new ChatInviteLink(this.client, this.raw.invite)) } } diff --git a/packages/client/src/types/updates/chosen-inline-result.ts b/packages/client/src/types/updates/chosen-inline-result.ts index c3f9437f..e6725a06 100644 --- a/packages/client/src/types/updates/chosen-inline-result.ts +++ b/packages/client/src/types/updates/chosen-inline-result.ts @@ -32,10 +32,7 @@ export class ChosenInlineResult { * User who has chosen the query */ get user(): User { - return (this._user ??= new User( - this.client, - this._peers.user(this.raw.userId), - )) + return (this._user ??= new User(this.client, this._peers.user(this.raw.userId))) } /** @@ -82,13 +79,9 @@ export class ChosenInlineResult { return encodeInlineMessageId(this.raw.msgId) } - async editMessage( - params: Parameters[1], - ): Promise { + async editMessage(params: Parameters[1]): Promise { if (!this.raw.msgId) { - throw new MtArgumentError( - 'No message ID, make sure you have included reply markup!', - ) + throw new MtArgumentError('No message ID, make sure you have included reply markup!') } return this.client.editInlineMessage(this.raw.msgId, params) diff --git a/packages/client/src/types/updates/delete-message-update.ts b/packages/client/src/types/updates/delete-message-update.ts index a7eeb0e3..e1c5fc66 100644 --- a/packages/client/src/types/updates/delete-message-update.ts +++ b/packages/client/src/types/updates/delete-message-update.ts @@ -10,9 +10,7 @@ import { makeInspectable } from '../utils' export class DeleteMessageUpdate { constructor( readonly client: TelegramClient, - readonly raw: - | tl.RawUpdateDeleteMessages - | tl.RawUpdateDeleteChannelMessages, + readonly raw: tl.RawUpdateDeleteMessages | tl.RawUpdateDeleteChannelMessages, ) {} /** @@ -26,9 +24,7 @@ export class DeleteMessageUpdate { * Marked ID of the channel where the messages were deleted */ get channelId(): number | null { - return this.raw._ === 'updateDeleteChannelMessages' ? - toggleChannelIdMark(this.raw.channelId) : - null + return this.raw._ === 'updateDeleteChannelMessages' ? toggleChannelIdMark(this.raw.channelId) : null } } diff --git a/packages/client/src/types/updates/parse-update.ts b/packages/client/src/types/updates/parse-update.ts index 010f8576..387f13e5 100644 --- a/packages/client/src/types/updates/parse-update.ts +++ b/packages/client/src/types/updates/parse-update.ts @@ -25,20 +25,14 @@ import { type ParserFunction = ( client: TelegramClient, upd: tl.TypeUpdate | tl.TypeMessage, - peers: PeersIndex + peers: PeersIndex, ) => ParsedUpdate['data'] type UpdateParser = [ParsedUpdate['name'], ParserFunction] -const baseMessageParser: ParserFunction = ( - client: TelegramClient, - upd, - peers, -) => +const baseMessageParser: ParserFunction = (client: TelegramClient, upd, peers) => new Message( client, - tl.isAnyMessage(upd) ? - upd : - (upd as { message: tl.TypeMessage }).message, + tl.isAnyMessage(upd) ? upd : (upd as { message: tl.TypeMessage }).message, peers, upd._ === 'updateNewScheduledMessage', ) @@ -53,22 +47,14 @@ const callbackQueryParser: UpdateParser = [ 'callback_query', (client, upd, peers) => new CallbackQuery(client, upd as any, peers), ] -const userTypingParser: UpdateParser = [ - 'user_typing', - (client, upd) => new UserTypingUpdate(client, upd as any), -] +const userTypingParser: UpdateParser = ['user_typing', (client, upd) => new UserTypingUpdate(client, upd as any)] const deleteMessageParser: UpdateParser = [ 'delete_message', (client, upd) => new DeleteMessageUpdate(client, upd as any), ] -const historyReadParser: UpdateParser = [ - 'history_read', - (client, upd) => new HistoryReadUpdate(client, upd as any), -] +const historyReadParser: UpdateParser = ['history_read', (client, upd) => new HistoryReadUpdate(client, upd as any)] -const PARSERS: Partial< - Record<(tl.TypeUpdate | tl.TypeMessage)['_'], UpdateParser> -> = { +const PARSERS: Partial> = { message: newMessageParser, messageEmpty: newMessageParser, messageService: newMessageParser, @@ -79,29 +65,16 @@ const PARSERS: Partial< updateEditChannelMessage: editMessageParser, updateChatParticipant: chatMemberParser, updateChannelParticipant: chatMemberParser, - updateBotInlineQuery: [ - 'inline_query', - (client, upd, peers) => new InlineQuery(client, upd as any, peers), - ], + updateBotInlineQuery: ['inline_query', (client, upd, peers) => new InlineQuery(client, upd as any, peers)], updateBotInlineSend: [ 'chosen_inline_result', - (client, upd, peers) => - new ChosenInlineResult(client, upd as any, peers), + (client, upd, peers) => new ChosenInlineResult(client, upd as any, peers), ], updateBotCallbackQuery: callbackQueryParser, updateInlineBotCallbackQuery: callbackQueryParser, - updateMessagePoll: [ - 'poll', - (client, upd, peers) => new PollUpdate(client, upd as any, peers), - ], - updateMessagePollVote: [ - 'poll_vote', - (client, upd, peers) => new PollVoteUpdate(client, upd as any, peers), - ], - updateUserStatus: [ - 'user_status', - (client, upd) => new UserStatusUpdate(client, upd as any), - ], + updateMessagePoll: ['poll', (client, upd, peers) => new PollUpdate(client, upd as any, peers)], + updateMessagePollVote: ['poll_vote', (client, upd, peers) => new PollVoteUpdate(client, upd as any, peers)], + updateUserStatus: ['user_status', (client, upd) => new UserStatusUpdate(client, upd as any)], updateChannelUserTyping: userTypingParser, updateChatUserTyping: userTypingParser, updateUserTyping: userTypingParser, @@ -113,19 +86,14 @@ const PARSERS: Partial< updateReadChannelOutbox: historyReadParser, updateReadChannelDiscussionInbox: historyReadParser, updateReadChannelDiscussionOutbox: historyReadParser, - updateBotStopped: [ - 'bot_stopped', - (client, upd, peers) => new BotStoppedUpdate(client, upd as any, peers), - ], + updateBotStopped: ['bot_stopped', (client, upd, peers) => new BotStoppedUpdate(client, upd as any, peers)], updateBotChatInviteRequester: [ 'bot_chat_join_request', - (client, upd, peers) => - new BotChatJoinRequestUpdate(client, upd as any, peers), + (client, upd, peers) => new BotChatJoinRequestUpdate(client, upd as any, peers), ], updatePendingJoinRequests: [ 'chat_join_request', - (client, upd, peers) => - new ChatJoinRequestUpdate(client, upd as any, peers), + (client, upd, peers) => new ChatJoinRequestUpdate(client, upd as any, peers), ], updateBotPrecheckoutQuery: [ 'pre_checkout_query', diff --git a/packages/client/src/types/updates/poll-update.ts b/packages/client/src/types/updates/poll-update.ts index eb56f9c5..0d3cda95 100644 --- a/packages/client/src/types/updates/poll-update.ts +++ b/packages/client/src/types/updates/poll-update.ts @@ -12,11 +12,7 @@ import { makeInspectable } from '../utils' * polls which were sent by this bot */ export class PollUpdate { - constructor( - readonly client: TelegramClient, - readonly raw: tl.RawUpdateMessagePoll, - readonly _peers: PeersIndex, - ) {} + constructor(readonly client: TelegramClient, readonly raw: tl.RawUpdateMessagePoll, readonly _peers: PeersIndex) {} /** * Unique poll ID @@ -62,12 +58,7 @@ export class PollUpdate { } } - this._poll = new Poll( - this.client, - poll, - this._peers, - this.raw.results, - ) + this._poll = new Poll(this.client, poll, this._peers, this.raw.results) } return this._poll diff --git a/packages/client/src/types/updates/poll-vote.ts b/packages/client/src/types/updates/poll-vote.ts index 5f123fa7..6e4ae97d 100644 --- a/packages/client/src/types/updates/poll-vote.ts +++ b/packages/client/src/types/updates/poll-vote.ts @@ -34,18 +34,12 @@ export class PollVoteUpdate { if (this._peer) return this._peer if (this.raw.peer._ === 'peerUser') { - return (this._peer = new User( - this.client, - this._peers.user(this.raw.peer.userId), - )) + return (this._peer = new User(this.client, this._peers.user(this.raw.peer.userId))) } assertTypeIs('PollVoteUpdate.peer', this.raw.peer, 'peerChannel') - return (this._peer = new User( - this.client, - this._peers.user(this.raw.peer.channelId), - )) + return (this._peer = new User(this.client, this._peers.user(this.raw.peer.channelId))) } /** @@ -87,9 +81,7 @@ export class PollVoteUpdate { throw new MtUnsupportedError('option had >1 byte') } if (buf[0] < 48 || buf[0] > 57) { - throw new MtUnsupportedError( - 'option had first byte out of 0-9 range', - ) + throw new MtUnsupportedError('option had first byte out of 0-9 range') } return buf[0] - 48 diff --git a/packages/client/src/types/updates/pre-checkout-query.ts b/packages/client/src/types/updates/pre-checkout-query.ts index fed2a290..f60e4de8 100644 --- a/packages/client/src/types/updates/pre-checkout-query.ts +++ b/packages/client/src/types/updates/pre-checkout-query.ts @@ -30,10 +30,7 @@ export class PreCheckoutQuery { * User who sent the query */ get user(): User { - return (this._user ??= new User( - this.client, - this._peers.user(this.userId), - )) + return (this._user ??= new User(this.client, this._peers.user(this.userId))) } /** diff --git a/packages/client/src/types/updates/user-status-update.ts b/packages/client/src/types/updates/user-status-update.ts index 9f90c84c..23447aa8 100644 --- a/packages/client/src/types/updates/user-status-update.ts +++ b/packages/client/src/types/updates/user-status-update.ts @@ -8,10 +8,7 @@ import { makeInspectable } from '../utils' * User status has changed */ export class UserStatusUpdate { - constructor( - readonly client: TelegramClient, - readonly raw: tl.RawUpdateUserStatus, - ) {} + constructor(readonly client: TelegramClient, readonly raw: tl.RawUpdateUserStatus) {} /** * ID of the user whose status has updated diff --git a/packages/client/src/types/updates/user-typing-update.ts b/packages/client/src/types/updates/user-typing-update.ts index 3ddae2d5..692d3629 100644 --- a/packages/client/src/types/updates/user-typing-update.ts +++ b/packages/client/src/types/updates/user-typing-update.ts @@ -1,8 +1,4 @@ -import { - getBarePeerId, - MtUnsupportedError, - toggleChannelIdMark, -} from '@mtcute/core' +import { getBarePeerId, MtUnsupportedError, toggleChannelIdMark } from '@mtcute/core' import { tl } from '@mtcute/tl' import { TelegramClient } from '../../client' @@ -17,19 +13,14 @@ import { makeInspectable } from '../utils' export class UserTypingUpdate { constructor( readonly client: TelegramClient, - readonly raw: - | tl.RawUpdateUserTyping - | tl.RawUpdateChatUserTyping - | tl.RawUpdateChannelUserTyping, + readonly raw: tl.RawUpdateUserTyping | tl.RawUpdateChatUserTyping | tl.RawUpdateChannelUserTyping, ) {} /** * ID of the user whose typing status changed */ get userId(): number { - return this.raw._ === 'updateUserTyping' ? - this.raw.userId : - getBarePeerId(this.raw.fromId) + return this.raw._ === 'updateUserTyping' ? this.raw.userId : getBarePeerId(this.raw.fromId) } /** diff --git a/packages/client/src/types/utils.ts b/packages/client/src/types/utils.ts index ae6b9846..5b0991a0 100644 --- a/packages/client/src/types/utils.ts +++ b/packages/client/src/types/utils.ts @@ -19,11 +19,7 @@ function getAllGettersNames(obj: object): string[] { do { Object.getOwnPropertyNames(obj).forEach((prop) => { - if ( - prop !== '__proto__' && - Object.getOwnPropertyDescriptor(obj, prop)?.get && - !getters.includes(prop) - ) { + if (prop !== '__proto__' && Object.getOwnPropertyDescriptor(obj, prop)?.get && !getters.includes(prop)) { getters.push(prop) } }) @@ -46,11 +42,7 @@ const bufferToJsonInspect = function (this: Buffer) { * > (getter that caches after its first invocation is also * > considered pure in this case) */ -export function makeInspectable( - obj: new (...args: any[]) => any, - props?: string[], - hide?: string[], -): void { +export function makeInspectable(obj: new (...args: any[]) => any, props?: string[], hide?: string[]): void { const getters: string[] = props ? props : [] for (const key of getAllGettersNames(obj.prototype)) { @@ -71,11 +63,7 @@ export function makeInspectable( try { let val = this[it] - if ( - val && - typeof val === 'object' && - typeof val.toJSON === 'function' - ) { + if (val && typeof val === 'object' && typeof val.toJSON === 'function') { val = val.toJSON(true) } ret[it] = val diff --git a/packages/client/src/utils/file-utils.ts b/packages/client/src/utils/file-utils.ts index a5d24481..82753f37 100644 --- a/packages/client/src/utils/file-utils.ts +++ b/packages/client/src/utils/file-utils.ts @@ -69,8 +69,7 @@ export function strippedPhotoToJpg(stripped: Buffer): Buffer { return result } -const SVG_LOOKUP = - 'AACAAAAHAAALMAAAQASTAVAAAZaacaaaahaaalmaaaqastava.az0123456789-,' +const SVG_LOOKUP = 'AACAAAAHAAALMAAAQASTAVAAAZaacaaaahaaalmaaaqastava.az0123456789-,' /** * Inflate compressed preview SVG path to full SVG path diff --git a/packages/client/src/utils/inline-utils.ts b/packages/client/src/utils/inline-utils.ts index b6f34b2c..3448ce86 100644 --- a/packages/client/src/utils/inline-utils.ts +++ b/packages/client/src/utils/inline-utils.ts @@ -7,9 +7,7 @@ import { tl } from '@mtcute/tl' * * @param id Inline message ID */ -export function parseInlineMessageId( - id: string, -): tl.TypeInputBotInlineMessageID { +export function parseInlineMessageId(id: string): tl.TypeInputBotInlineMessageID { const buf = parseUrlSafeBase64(id) const reader = TlBinaryReader.manual(buf) @@ -36,9 +34,7 @@ export function parseInlineMessageId( * * @param id Inline message ID object */ -export function encodeInlineMessageId( - id: tl.TypeInputBotInlineMessageID, -): string { +export function encodeInlineMessageId(id: tl.TypeInputBotInlineMessageID): string { let writer: TlBinaryWriter switch (id._) { diff --git a/packages/client/src/utils/misc-utils.ts b/packages/client/src/utils/misc-utils.ts index dd9b451b..2e4511e9 100644 --- a/packages/client/src/utils/misc-utils.ts +++ b/packages/client/src/utils/misc-utils.ts @@ -18,9 +18,7 @@ export async function resolveMaybeDynamic(val: MaybeDynamic): Promise { return val instanceof Function ? await val() : await val } -export function extractChannelIdFromUpdate( - upd: tl.TypeUpdate, -): number | undefined { +export function extractChannelIdFromUpdate(upd: tl.TypeUpdate): number | undefined { // holy shit let res = 0 @@ -41,17 +39,11 @@ export function extractChannelIdFromUpdate( return res } -export function normalizeDate( - date: Date | number | undefined, -): number | undefined { - return date ? - ~~((typeof date === 'number' ? date : date.getTime()) / 1000) : - undefined +export function normalizeDate(date: Date | number | undefined): number | undefined { + return date ? ~~((typeof date === 'number' ? date : date.getTime()) / 1000) : undefined } -export function normalizeMessageId( - msg: Message | number | undefined, -): number | undefined { +export function normalizeMessageId(msg: Message | number | undefined): number | undefined { if (!msg) return undefined return typeof msg === 'number' ? msg : msg.id diff --git a/packages/client/src/utils/peer-utils.ts b/packages/client/src/utils/peer-utils.ts index a2c63d45..270949e9 100644 --- a/packages/client/src/utils/peer-utils.ts +++ b/packages/client/src/utils/peer-utils.ts @@ -10,9 +10,7 @@ export const INVITE_LINK_REGEX = // helpers to normalize result of `resolvePeer` function -export function normalizeToInputPeer( - res: tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel, -): tl.TypeInputPeer { +export function normalizeToInputPeer(res: tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel): tl.TypeInputPeer { if (tl.isAnyInputPeer(res)) return res switch (res._) { @@ -106,10 +104,7 @@ export function normalizeToInputChannel( export function isInputPeerUser( obj: tl.TypeInputPeer, -): obj is - | tl.RawInputPeerUser - | tl.RawInputPeerUserFromMessage - | tl.RawInputPeerSelf { +): obj is tl.RawInputPeerUser | tl.RawInputPeerUserFromMessage | tl.RawInputPeerSelf { switch (obj._) { case 'inputPeerUser': case 'inputPeerUserFromMessage': @@ -132,9 +127,7 @@ export function isInputPeerChannel( return false } -export function isInputPeerChat( - obj: tl.TypeInputPeer, -): obj is tl.RawInputPeerChat { +export function isInputPeerChat(obj: tl.TypeInputPeer): obj is tl.RawInputPeerChat { return obj._ === 'inputPeerChat' } @@ -153,10 +146,7 @@ export function inputPeerToPeer(inp: tl.TypeInputPeer): tl.TypePeer { } } -export function peerToInputPeer( - peer: tl.TypePeer, - accessHash = Long.ZERO, -): tl.TypeInputPeer { +export function peerToInputPeer(peer: tl.TypePeer, accessHash = Long.ZERO): tl.TypeInputPeer { switch (peer._) { case 'peerUser': return { _: 'inputPeerUser', userId: peer.userId, accessHash } diff --git a/packages/client/src/utils/stream-utils.ts b/packages/client/src/utils/stream-utils.ts index b507a14a..d3ebd7ac 100644 --- a/packages/client/src/utils/stream-utils.ts +++ b/packages/client/src/utils/stream-utils.ts @@ -64,10 +64,7 @@ class NodeReadable extends Readable { } } - _handleDestroy( - err: Error | null, - callback: (error?: Error | null) => void, - ) { + _handleDestroy(err: Error | null, callback: (error?: Error | null) => void) { this._webStream .cancel() .then(() => super._destroy(err, callback)) @@ -75,10 +72,7 @@ class NodeReadable extends Readable { } } -export function convertWebStreamToNodeReadable( - webStream: ReadableStream, - opts?: ReadableOptions, -): Readable { +export function convertWebStreamToNodeReadable(webStream: ReadableStream, opts?: ReadableOptions): Readable { return new NodeReadable(webStream, opts) } @@ -91,10 +85,7 @@ export function bufferToStream(buf: Buffer): Readable { }) } -export async function readBytesFromStream( - stream: Readable, - size: number, -): Promise { +export async function readBytesFromStream(stream: Readable, size: number): Promise { if (stream.readableEnded) return null let res = stream.read(size) as Buffer diff --git a/packages/client/src/utils/updates-utils.ts b/packages/client/src/utils/updates-utils.ts index 7ed97b62..68384109 100644 --- a/packages/client/src/utils/updates-utils.ts +++ b/packages/client/src/utils/updates-utils.ts @@ -11,11 +11,7 @@ import { tl } from '@mtcute/tl' * @param ptsCount PTS count * @param channelId Channel ID (bare), if applicable */ -export function createDummyUpdate( - pts: number, - ptsCount: number, - channelId = 0, -): tl.TypeUpdates { +export function createDummyUpdate(pts: number, ptsCount: number, channelId = 0): tl.TypeUpdates { return { _: 'updates', seq: 0, diff --git a/packages/client/src/utils/voice-utils.ts b/packages/client/src/utils/voice-utils.ts index c364d774..0575a89b 100644 --- a/packages/client/src/utils/voice-utils.ts +++ b/packages/client/src/utils/voice-utils.ts @@ -31,10 +31,7 @@ export function decodeWaveform(wf: Buffer): number[] { const lastByteIdx = ~~((lastIdx * 5) / 8) const lastBitShift = (lastIdx * 5) % 8 - const lastValue = - lastByteIdx === wf.length - 1 ? - wf[lastByteIdx] : - wf.readUInt16LE(lastByteIdx) + const lastValue = lastByteIdx === wf.length - 1 ? wf[lastByteIdx] : wf.readUInt16LE(lastByteIdx) result[lastIdx] = (lastValue >> lastBitShift) & 0b11111 return result diff --git a/packages/client/tests/buffer-utils.spec.ts b/packages/client/tests/buffer-utils.spec.ts index 3d8f2d06..079f3b1d 100644 --- a/packages/client/tests/buffer-utils.spec.ts +++ b/packages/client/tests/buffer-utils.spec.ts @@ -5,58 +5,21 @@ import { isProbablyPlainText } from '../src/utils/file-utils' describe('isProbablyPlainText', () => { it('should return true for buffers only containing printable ascii', () => { - expect( - isProbablyPlainText(Buffer.from('hello this is some ascii text')), - ).to.be.true - expect( - isProbablyPlainText( - Buffer.from( - 'hello this is some ascii text\nwith unix new lines', - ), - ), - ).to.be.true - expect( - isProbablyPlainText( - Buffer.from( - 'hello this is some ascii text\r\nwith windows new lines', - ), - ), - ).to.be.true - expect( - isProbablyPlainText( - Buffer.from( - 'hello this is some ascii text\n\twith unix new lines and tabs', - ), - ), - ).to.be.true - expect( - isProbablyPlainText( - Buffer.from( - 'hello this is some ascii text\r\n\twith windows new lines and tabs', - ), - ), - ).to.be.true + expect(isProbablyPlainText(Buffer.from('hello this is some ascii text'))).to.be.true + expect(isProbablyPlainText(Buffer.from('hello this is some ascii text\nwith unix new lines'))).to.be.true + expect(isProbablyPlainText(Buffer.from('hello this is some ascii text\r\nwith windows new lines'))).to.be.true + expect(isProbablyPlainText(Buffer.from('hello this is some ascii text\n\twith unix new lines and tabs'))).to.be + .true + expect(isProbablyPlainText(Buffer.from('hello this is some ascii text\r\n\twith windows new lines and tabs'))) + .to.be.true }) it('should return false for buffers containing some binary data', () => { - expect(isProbablyPlainText(Buffer.from('hello this is cedilla: ç'))).to - .be.false - expect( - isProbablyPlainText( - Buffer.from('hello this is some ascii text with emojis 🌸'), - ), - ).to.be.false + expect(isProbablyPlainText(Buffer.from('hello this is cedilla: ç'))).to.be.false + expect(isProbablyPlainText(Buffer.from('hello this is some ascii text with emojis 🌸'))).to.be.false // random strings of 16 bytes - expect( - isProbablyPlainText( - Buffer.from('717f80f08eb9d88c3931712c0e2be32f', 'hex'), - ), - ).to.be.false - expect( - isProbablyPlainText( - Buffer.from('20e8e218e54254c813b261432b0330d7', 'hex'), - ), - ).to.be.false + expect(isProbablyPlainText(Buffer.from('717f80f08eb9d88c3931712c0e2be32f', 'hex'))).to.be.false + expect(isProbablyPlainText(Buffer.from('20e8e218e54254c813b261432b0330d7', 'hex'))).to.be.false }) }) diff --git a/packages/core/src/base-client.ts b/packages/core/src/base-client.ts index ae3a1a99..cc3de8b0 100644 --- a/packages/core/src/base-client.ts +++ b/packages/core/src/base-client.ts @@ -7,17 +7,9 @@ import defaultReaderMap from '@mtcute/tl/binary/reader' import defaultWriterMap from '@mtcute/tl/binary/writer' import { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime' -import { - ReconnectionStrategy, - SessionConnection, - TransportFactory, -} from './network' +import { ReconnectionStrategy, SessionConnection, TransportFactory } from './network' import { ConfigManager } from './network/config-manager' -import { - NetworkManager, - NetworkManagerExtraParams, - RpcCallOptions, -} from './network/network-manager' +import { NetworkManager, NetworkManagerExtraParams, RpcCallOptions } from './network/network-manager' import { PersistentConnectionParams } from './network/persistent-connection' import { ITelegramStorage, MemoryStorage } from './storage' import { MustEqual } from './types' @@ -94,9 +86,7 @@ export interface BaseTelegramClientOptions { * `apiId` and `query` are not available and will be ignored. * Omitted values will be filled with defaults */ - initConnectionOptions?: Partial< - Omit - > + initConnectionOptions?: Partial> /** * Transport factory to use in the client. @@ -223,9 +213,7 @@ export class BaseTelegramClient extends EventEmitter { protected _lastUpdateTime = 0 - protected _config = new ConfigManager(() => - this.call({ _: 'help.getConfig' }), - ) + protected _config = new ConfigManager(() => this.call({ _: 'help.getConfig' })) // not really connected, but rather "connect() was called" private _connected: ControllablePromise | boolean = false @@ -251,8 +239,7 @@ export class BaseTelegramClient extends EventEmitter { constructor(opts: BaseTelegramClientOptions) { super() - const apiId = - typeof opts.apiId === 'string' ? parseInt(opts.apiId) : opts.apiId + const apiId = typeof opts.apiId === 'string' ? parseInt(opts.apiId) : opts.apiId if (isNaN(apiId)) { throw new Error('apiId must be a number or a numeric string!') @@ -270,9 +257,7 @@ export class BaseTelegramClient extends EventEmitter { if (this._testMode) { dc = this._useIpv6 ? defaultTestIpv6Dc : defaultTestDc } else { - dc = this._useIpv6 ? - defaultProductionIpv6Dc : - defaultProductionDc + dc = this._useIpv6 ? defaultProductionIpv6Dc : defaultProductionDc } } @@ -351,9 +336,7 @@ export class BaseTelegramClient extends EventEmitter { const primaryDc = await this.storage.getDefaultDcs() if (primaryDc !== null) this._defaultDcs = primaryDc - const defaultDcAuthKey = await this.storage.getAuthKeyFor( - this._defaultDcs.main.id, - ) + const defaultDcAuthKey = await this.storage.getAuthKeyFor(this._defaultDcs.main.id) if ((this._importForce || !defaultDcAuthKey) && this._importFrom) { const data = readStringSession(this._readerMap, this._importFrom) @@ -361,9 +344,7 @@ export class BaseTelegramClient extends EventEmitter { if (data.testMode !== this._testMode) { throw new Error( 'This session string is not for the current backend. ' + - `Session is ${ - data.testMode ? 'test' : 'prod' - }, but the client is ${ + `Session is ${data.testMode ? 'test' : 'prod'}, but the client is ${ this._testMode ? 'test' : 'prod' }`, ) @@ -377,10 +358,7 @@ export class BaseTelegramClient extends EventEmitter { } // await this.primaryConnection.setupKeys(data.authKey) - await this.storage.setAuthKeyFor( - data.primaryDcs.main.id, - data.authKey, - ) + await this.storage.setAuthKeyFor(data.primaryDcs.main.id, data.authKey) await this._saveStorage(true) } @@ -466,9 +444,7 @@ export class BaseTelegramClient extends EventEmitter { * the connection in which the error has occurred, in case * this was connection-related error. */ - onError( - handler: (err: unknown, connection?: SessionConnection) => void, - ): void { + onError(handler: (err: unknown, connection?: SessionConnection) => void): void { this._onError = handler } @@ -505,10 +481,7 @@ export class BaseTelegramClient extends EventEmitter { switch (peer._) { case 'user': if (!peer.accessHash) { - this.log.warn( - 'received user without access hash: %j', - peer, - ) + this.log.warn('received user without access hash: %j', peer) continue } @@ -533,19 +506,13 @@ export class BaseTelegramClient extends EventEmitter { case 'channel': case 'channelForbidden': if (!peer.accessHash) { - this.log.warn( - 'received user without access hash: %j', - peer, - ) + this.log.warn('received user without access hash: %j', peer) continue } parsedPeers.push({ id: toggleChannelIdMark(peer.id), accessHash: peer.accessHash, - username: - peer._ === 'channel' ? - peer.username?.toLowerCase() : - undefined, + username: peer._ === 'channel' ? peer.username?.toLowerCase() : undefined, type: 'channel', full: peer, }) diff --git a/packages/core/src/network/auth-key.ts b/packages/core/src/network/auth-key.ts index a8e4b297..acd2bc62 100644 --- a/packages/core/src/network/auth-key.ts +++ b/packages/core/src/network/auth-key.ts @@ -15,11 +15,7 @@ export class AuthKey { clientSalt!: Buffer serverSalt!: Buffer - constructor( - readonly _crypto: ICryptoProvider, - readonly log: Logger, - readonly _readerMap: TlReaderMap, - ) {} + constructor(readonly _crypto: ICryptoProvider, readonly log: Logger, readonly _readerMap: TlReaderMap) {} match(keyId: Buffer): boolean { return this.ready && buffersEqual(keyId, this.id) @@ -37,15 +33,10 @@ export class AuthKey { this.log.verbose('auth key set up, id = %h', this.id) } - async encryptMessage( - message: Buffer, - serverSalt: Long, - sessionId: Long, - ): Promise { + async encryptMessage(message: Buffer, serverSalt: Long, sessionId: Long): Promise { if (!this.ready) throw new MtcuteError('Keys are not set up!') - let padding = - (16 /* header size */ + message.length + 12) /* min padding */ % 16 + let padding = (16 /* header size */ + message.length + 12) /* min padding */ % 16 padding = 12 + (padding ? 16 - padding : 0) const buf = Buffer.alloc(16 + message.length + padding) @@ -57,15 +48,8 @@ export class AuthKey { message.copy(buf, 16) randomBytes(padding).copy(buf, 16 + message.length) - const messageKey = ( - await this._crypto.sha256(Buffer.concat([this.clientSalt, buf])) - ).slice(8, 24) - const ige = await createAesIgeForMessage( - this._crypto, - this.key, - messageKey, - true, - ) + const messageKey = (await this._crypto.sha256(Buffer.concat([this.clientSalt, buf]))).slice(8, 24) + const ige = await createAesIgeForMessage(this._crypto, this.key, messageKey, true) const encryptedData = await ige.encrypt(buf) return Buffer.concat([this.id, messageKey, encryptedData]) @@ -79,19 +63,10 @@ export class AuthKey { const messageKey = data.slice(8, 24) const encryptedData = data.slice(24) - const ige = await createAesIgeForMessage( - this._crypto, - this.key, - messageKey, - false, - ) + const ige = await createAesIgeForMessage(this._crypto, this.key, messageKey, false) const innerData = await ige.decrypt(encryptedData) - const expectedMessageKey = ( - await this._crypto.sha256( - Buffer.concat([this.serverSalt, innerData]), - ) - ).slice(8, 24) + const expectedMessageKey = (await this._crypto.sha256(Buffer.concat([this.serverSalt, innerData]))).slice(8, 24) if (!buffersEqual(messageKey, expectedMessageKey)) { this.log.warn( @@ -109,10 +84,7 @@ export class AuthKey { const messageId = innerReader.long(true) if (sessionId_.neq(sessionId)) { - this.log.warn( - 'ignoring message with invalid sessionId = %h', - sessionId_, - ) + this.log.warn('ignoring message with invalid sessionId = %h', sessionId_) return } @@ -121,20 +93,13 @@ export class AuthKey { const length = innerReader.uint() if (length > innerData.length - 32 /* header size */) { - this.log.warn( - 'ignoring message with invalid length: %d > %d', - length, - innerData.length - 32, - ) + this.log.warn('ignoring message with invalid length: %d > %d', length, innerData.length - 32) return } if (length % 4 !== 0) { - this.log.warn( - 'ignoring message with invalid length: %d is not a multiple of 4', - length, - ) + this.log.warn('ignoring message with invalid length: %d is not a multiple of 4', length) return } @@ -142,10 +107,7 @@ export class AuthKey { const paddingSize = innerData.length - length - 32 // header size if (paddingSize < 12 || paddingSize > 1024) { - this.log.warn( - 'ignoring message with invalid padding size: %d', - paddingSize, - ) + this.log.warn('ignoring message with invalid padding size: %d', paddingSize) return } diff --git a/packages/core/src/network/authorization.ts b/packages/core/src/network/authorization.ts index 43ddfcc0..d0af4fa5 100644 --- a/packages/core/src/network/authorization.ts +++ b/packages/core/src/network/authorization.ts @@ -3,29 +3,11 @@ import Long from 'long' import { mtp } from '@mtcute/tl' import { TlPublicKey } from '@mtcute/tl/binary/rsa-keys' -import { - TlBinaryReader, - TlBinaryWriter, - TlSerializationCounter, -} from '@mtcute/tl-runtime' +import { TlBinaryReader, TlBinaryWriter, TlSerializationCounter } from '@mtcute/tl-runtime' -import { - MtArgumentError, - MtSecurityError, - MtTypeAssertionError, -} from '../types' -import { - bigIntToBuffer, - bufferToBigInt, - ICryptoProvider, - Logger, -} from '../utils' -import { - buffersEqual, - randomBytes, - xorBuffer, - xorBufferInPlace, -} from '../utils/buffer-utils' +import { MtArgumentError, MtSecurityError, MtTypeAssertionError } from '../types' +import { bigIntToBuffer, bufferToBigInt, ICryptoProvider, Logger } from '../utils' +import { buffersEqual, randomBytes, xorBuffer, xorBufferInPlace } from '../utils/buffer-utils' import { findKeyByFingerprints } from '../utils/crypto/keys' import { millerRabin } from '../utils/crypto/miller-rabin' import { generateKeyAndIvFromNonce } from '../utils/crypto/mtproto' @@ -59,22 +41,15 @@ function checkDhPrime(log: Logger, dhPrime: bigInt.BigInteger, g: number) { let checkedPrime = checkedPrimesCache.find((x) => x.prime.eq(dhPrime)) if (!checkedPrime) { - if ( - dhPrime.lesserOrEquals(TWO_POW_2047) || - dhPrime.greaterOrEquals(TWO_POW_2048) - ) { - throw new MtSecurityError( - 'Step 3: dh_prime is not in the 2048-bit range', - ) + if (dhPrime.lesserOrEquals(TWO_POW_2047) || dhPrime.greaterOrEquals(TWO_POW_2048)) { + throw new MtSecurityError('Step 3: dh_prime is not in the 2048-bit range') } if (!millerRabin(dhPrime)) { throw new MtSecurityError('Step 3: dh_prime is not prime') } if (!millerRabin(dhPrime.minus(1).divide(2))) { - throw new MtSecurityError( - 'Step 3: dh_prime is not a safe prime - (dh_prime-1)/2 is not prime', - ) + throw new MtSecurityError('Step 3: dh_prime is not a safe prime - (dh_prime-1)/2 is not prime') } log.debug('dh_prime is probably prime') @@ -99,16 +74,12 @@ function checkDhPrime(log: Logger, dhPrime: bigInt.BigInteger, g: number) { switch (g) { case 2: if (dhPrime.mod(8).notEquals(7)) { - throw new MtSecurityError( - '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 MtSecurityError( - 'Step 3: ivalid g - dh_prime mod 3 != 2', - ) + throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 3 != 2') } break case 4: @@ -117,9 +88,7 @@ function checkDhPrime(log: Logger, dhPrime: bigInt.BigInteger, g: number) { const mod = dhPrime.mod(5) if (mod.notEquals(1) && mod.notEquals(4)) { - throw new MtSecurityError( - 'Step 3: ivalid g - dh_prime mod 5 != 1 && dh_prime mod 5 != 4', - ) + throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 5 != 1 && dh_prime mod 5 != 4') } break } @@ -127,9 +96,7 @@ function checkDhPrime(log: Logger, dhPrime: bigInt.BigInteger, g: number) { const mod = dhPrime.mod(24) if (mod.notEquals(19) && mod.notEquals(23)) { - throw new MtSecurityError( - 'Step 3: ivalid g - dh_prime mod 24 != 19 && dh_prime mod 24 != 23', - ) + throw new MtSecurityError('Step 3: ivalid g - dh_prime mod 24 != 19 && dh_prime mod 24 != 23') } break } @@ -152,11 +119,7 @@ function checkDhPrime(log: Logger, dhPrime: bigInt.BigInteger, g: number) { log.debug('g = %d is safe to use with dh_prime', g) } -async function rsaPad( - data: Buffer, - crypto: ICryptoProvider, - key: TlPublicKey, -): Promise { +async function rsaPad(data: Buffer, crypto: ICryptoProvider, key: TlPublicKey): Promise { // since Summer 2021, they use "version of RSA with a variant of OAEP+ padding explained below" const keyModulus = bigInt(key.modulus, 16) @@ -173,10 +136,7 @@ async function rsaPad( const aesKey = randomBytes(32) - const dataWithHash = Buffer.concat([ - data, - await crypto.sha256(Buffer.concat([aesKey, data])), - ]) + const dataWithHash = Buffer.concat([data, await crypto.sha256(Buffer.concat([aesKey, data]))]) // we only need to reverse the data dataWithHash.slice(0, 192).reverse() @@ -193,20 +153,13 @@ async function rsaPad( continue } - const encryptedBigint = decryptedDataBigint.modPow( - keyExponent, - keyModulus, - ) + const encryptedBigint = decryptedDataBigint.modPow(keyExponent, keyModulus) return bigIntToBuffer(encryptedBigint, 256) } } -async function rsaEncrypt( - data: Buffer, - crypto: ICryptoProvider, - key: TlPublicKey, -): Promise { +async function rsaEncrypt(data: Buffer, crypto: ICryptoProvider, key: TlPublicKey): Promise { const toEncrypt = Buffer.concat([ await crypto.sha1(data), data, @@ -214,10 +167,7 @@ async function rsaEncrypt( randomBytes(235 - data.length), ]) - const encryptedBigInt = bufferToBigInt(toEncrypt).modPow( - bigInt(key.exponent, 16), - bigInt(key.modulus, 16), - ) + const encryptedBigInt = bufferToBigInt(toEncrypt).modPow(bigInt(key.exponent, 16), bigInt(key.modulus, 16)) return bigIntToBuffer(encryptedBigInt) } @@ -239,10 +189,7 @@ export async function doAuthorization( const log = connection.log.create('auth') function sendPlainMessage(message: mtp.TlObject): Promise { - const length = TlSerializationCounter.countNeededBytes( - writerMap, - message, - ) + const length = TlSerializationCounter.countNeededBytes(writerMap, message) const writer = TlBinaryWriter.alloc(writerMap, length + 20) // 20 bytes for mtproto header const messageId = session.getMessageId() @@ -283,9 +230,7 @@ export async function doAuthorization( throw new MtSecurityError('Step 1: invalid nonce from server') } - const serverKeys = resPq.serverPublicKeyFingerprints.map((it) => - it.toUnsigned().toString(16), - ) + const serverKeys = resPq.serverPublicKeyFingerprints.map((it) => it.toUnsigned().toString(16)) log.debug('received PQ, keys: %j', serverKeys) // Step 2: DH exchange @@ -293,15 +238,10 @@ export async function doAuthorization( if (!publicKey) { throw new MtSecurityError( - 'Step 2: Could not find server public key with any of these fingerprints: ' + - serverKeys.join(', '), + 'Step 2: Could not find server public key with any of these fingerprints: ' + serverKeys.join(', '), ) } - log.debug( - 'found server key, fp = %s, old = %s', - publicKey.fingerprint, - publicKey.old, - ) + log.debug('found server key, fp = %s, old = %s', publicKey.fingerprint, publicKey.old) const [p, q] = await crypto.factorizePQ(resPq.pq) log.debug('factorized PQ: PQ = %h, P = %h, Q = %h', resPq.pq, p, q) @@ -367,30 +307,15 @@ export async function doAuthorization( } // Step 3: complete DH exchange - const [key, iv] = await generateKeyAndIvFromNonce( - crypto, - resPq.serverNonce, - newNonce, - ) + const [key, iv] = await generateKeyAndIvFromNonce(crypto, resPq.serverNonce, newNonce) const ige = crypto.createAesIge(key, iv) const plainTextAnswer = await ige.decrypt(serverDhParams.encryptedAnswer) const innerDataHash = plainTextAnswer.slice(0, 20) - const serverDhInnerReader = new TlBinaryReader( - readerMap, - plainTextAnswer, - 20, - ) + const serverDhInnerReader = new TlBinaryReader(readerMap, plainTextAnswer, 20) const serverDhInner = serverDhInnerReader.object() as mtp.TlObject - if ( - !buffersEqual( - innerDataHash, - await crypto.sha1( - plainTextAnswer.slice(20, serverDhInnerReader.pos), - ), - ) - ) { + if (!buffersEqual(innerDataHash, await crypto.sha1(plainTextAnswer.slice(20, serverDhInnerReader.pos)))) { throw new MtSecurityError('Step 3: invalid inner data hash') } @@ -412,10 +337,7 @@ export async function doAuthorization( checkDhPrime(log, dhPrime, serverDhInner.g) let retryId = Long.ZERO - const serverSalt = xorBuffer( - newNonce.slice(0, 8), - resPq.serverNonce.slice(0, 8), - ) + const serverSalt = xorBuffer(newNonce.slice(0, 8), resPq.serverNonce.slice(0, 8)) for (;;) { const b = bufferToBigInt(randomBytes(256)) @@ -425,34 +347,21 @@ export async function doAuthorization( const authKeyAuxHash = (await crypto.sha1(authKey)).slice(0, 8) // validate DH params - if ( - g.lesserOrEquals(1) || - g.greaterOrEquals(dhPrime.minus(bigInt.one)) - ) { + if (g.lesserOrEquals(1) || g.greaterOrEquals(dhPrime.minus(bigInt.one))) { throw new MtSecurityError('g is not within (1, dh_prime - 1)') } - if ( - gA.lesserOrEquals(1) || - gA.greaterOrEquals(dhPrime.minus(bigInt.one)) - ) { + if (gA.lesserOrEquals(1) || gA.greaterOrEquals(dhPrime.minus(bigInt.one))) { throw new MtSecurityError('g_a is not within (1, dh_prime - 1)') } - if ( - gB.lesserOrEquals(1) || - gB.greaterOrEquals(dhPrime.minus(bigInt.one)) - ) { + if (gB.lesserOrEquals(1) || gB.greaterOrEquals(dhPrime.minus(bigInt.one))) { 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 MtSecurityError( - 'g_a is not within (2^{2048-64}, dh_prime - 2^{2048-64})', - ) + 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 MtSecurityError( - 'g_b is not within (2^{2048-64}, dh_prime - 2^{2048-64})', - ) + throw new MtSecurityError('g_b is not within (2^{2048-64}, dh_prime - 2^{2048-64})') } const gB_ = bigIntToBuffer(gB, 0, false) @@ -465,18 +374,14 @@ export async function doAuthorization( retryId, gB: gB_, } - let innerLength = - TlSerializationCounter.countNeededBytes(writerMap, clientDhInner) + - 20 // for hash + let innerLength = TlSerializationCounter.countNeededBytes(writerMap, clientDhInner) + 20 // for hash const innerPaddingLength = innerLength % 16 if (innerPaddingLength > 0) innerLength += 16 - innerPaddingLength const clientDhInnerWriter = TlBinaryWriter.alloc(writerMap, innerLength) clientDhInnerWriter.pos = 20 clientDhInnerWriter.object(clientDhInner) - const clientDhInnerHash = await crypto.sha1( - clientDhInnerWriter.buffer.slice(20, clientDhInnerWriter.pos), - ) + const clientDhInnerHash = await crypto.sha1(clientDhInnerWriter.buffer.slice(20, clientDhInnerWriter.pos)) clientDhInnerWriter.pos = 0 clientDhInnerWriter.raw(clientDhInnerHash) @@ -493,11 +398,7 @@ export async function doAuthorization( const dhGen = await readNext() if (!mtp.isAnySet_client_DH_params_answer(dhGen)) { - throw new MtTypeAssertionError( - 'auth step 4', - 'set_client_DH_params_answer', - dhGen._, - ) + throw new MtTypeAssertionError('auth step 4', 'set_client_DH_params_answer', dhGen._) } if (!buffersEqual(dhGen.nonce, nonce)) { @@ -511,17 +412,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 MtTypeAssertionError( - 'auth step 4', - '!mt_dh_gen_fail', - dhGen._, - ) + throw new MtTypeAssertionError('auth step 4', '!mt_dh_gen_fail', dhGen._) } if (dhGen._ === 'mt_dh_gen_retry') { - const expectedHash = await crypto.sha1( - Buffer.concat([newNonce, Buffer.from([2]), authKeyAuxHash]), - ) + const expectedHash = await crypto.sha1(Buffer.concat([newNonce, Buffer.from([2]), authKeyAuxHash])) if (!buffersEqual(expectedHash.slice(4, 20), dhGen.newNonceHash2)) { throw Error('Step 4: invalid retry nonce hash from server') @@ -532,9 +427,7 @@ export async function doAuthorization( if (dhGen._ !== 'mt_dh_gen_ok') throw new Error() // unreachable - const expectedHash = await crypto.sha1( - Buffer.concat([newNonce, Buffer.from([1]), authKeyAuxHash]), - ) + const expectedHash = await crypto.sha1(Buffer.concat([newNonce, Buffer.from([1]), authKeyAuxHash])) if (!buffersEqual(expectedHash.slice(4, 20), dhGen.newNonceHash1)) { throw Error('Step 4: invalid nonce hash from server') @@ -542,10 +435,6 @@ export async function doAuthorization( log.info('authorization successful') - return [ - authKey, - new Long(serverSalt.readInt32LE(), serverSalt.readInt32LE(4)), - timeOffset, - ] + return [authKey, new Long(serverSalt.readInt32LE(), serverSalt.readInt32LE(4)), timeOffset] } } diff --git a/packages/core/src/network/index.ts b/packages/core/src/network/index.ts index b066008a..cbc1ccb6 100644 --- a/packages/core/src/network/index.ts +++ b/packages/core/src/network/index.ts @@ -1,8 +1,4 @@ -export { - ConnectionKind, - NetworkManagerExtraParams, - RpcCallOptions, -} from './network-manager' +export { ConnectionKind, NetworkManagerExtraParams, RpcCallOptions } from './network-manager' export * from './reconnection' export * from './session-connection' export * from './transports' diff --git a/packages/core/src/network/mtproto-session.ts b/packages/core/src/network/mtproto-session.ts index 4d575062..063b6f4f 100644 --- a/packages/core/src/network/mtproto-session.ts +++ b/packages/core/src/network/mtproto-session.ts @@ -1,12 +1,7 @@ import Long from 'long' import { mtp, tl } from '@mtcute/tl' -import { - TlBinaryWriter, - TlReaderMap, - TlSerializationCounter, - TlWriterMap, -} from '@mtcute/tl-runtime' +import { TlBinaryWriter, TlReaderMap, TlSerializationCounter, TlWriterMap } from '@mtcute/tl-runtime' import { MtcuteError } from '../types' import { @@ -111,10 +106,7 @@ export class MtprotoSession { queuedStateReq: Long[] = [] queuedResendReq: Long[] = [] queuedCancelReq: Long[] = [] - getStateSchedule = new SortedArray( - [], - (a, b) => a.getState! - b.getState!, - ) + getStateSchedule = new SortedArray([], (a, b) => a.getState! - b.getState!) // requests info pendingMessages = new LongMap() @@ -215,11 +207,7 @@ export class MtprotoSession { rpc.sent = false rpc.containerId = undefined - this.log.debug( - 'enqueued %s for sending (msg_id = %s)', - rpc.method, - rpc.msgId || 'n/a', - ) + this.log.debug('enqueued %s for sending (msg_id = %s)', rpc.method, rpc.msgId || 'n/a') this.queuedRpc.pushBack(rpc) return true @@ -261,10 +249,7 @@ export class MtprotoSession { } /** Decrypt a single MTProto message using session's keys */ - async decryptMessage( - data: Buffer, - callback: Parameters[2], - ): Promise { + async decryptMessage(data: Buffer, callback: Parameters[2]): Promise { if (!this._authKey.ready) throw new MtcuteError('Keys are not set up!') const authKeyId = data.slice(0, 8) @@ -292,20 +277,13 @@ export class MtprotoSession { return key.decryptMessage(data, this._sessionId, callback) } - writeMessage( - writer: TlBinaryWriter, - content: tl.TlObject | mtp.TlObject | Buffer, - isContentRelated = true, - ): Long { + writeMessage(writer: TlBinaryWriter, content: tl.TlObject | mtp.TlObject | Buffer, isContentRelated = true): Long { const messageId = this.getMessageId() const seqNo = this.getSeqNo(isContentRelated) const length = Buffer.isBuffer(content) ? content.length : - TlSerializationCounter.countNeededBytes( - writer.objectMap!, - content, - ) + TlSerializationCounter.countNeededBytes(writer.objectMap!, content) writer.long(messageId) writer.int(seqNo) @@ -337,10 +315,7 @@ export class MtprotoSession { this.next429Timeout = 1000 }, 60000) - this.log.debug( - 'transport flood, waiting for %d ms before proceeding', - timeout, - ) + this.log.debug('transport flood, waiting for %d ms before proceeding', timeout) return Date.now() + timeout } diff --git a/packages/core/src/network/multi-session-connection.ts b/packages/core/src/network/multi-session-connection.ts index a5b7e480..30909bed 100644 --- a/packages/core/src/network/multi-session-connection.ts +++ b/packages/core/src/network/multi-session-connection.ts @@ -4,10 +4,7 @@ import { tl } from '@mtcute/tl' import { Logger } from '../utils' import { MtprotoSession } from './mtproto-session' -import { - SessionConnection, - SessionConnectionParams, -} from './session-connection' +import { SessionConnection, SessionConnectionParams } from './session-connection' import { TransportFactory } from './transports' export class MultiSessionConnection extends EventEmitter { @@ -15,12 +12,7 @@ export class MultiSessionConnection extends EventEmitter { readonly _sessions: MtprotoSession[] private _enforcePfs = false - constructor( - readonly params: SessionConnectionParams, - private _count: number, - log: Logger, - logPrefix = '', - ) { + constructor(readonly params: SessionConnectionParams, private _count: number, log: Logger, logPrefix = '') { super() this._log = log.create('multi') if (logPrefix) this._log.prefix = `[${logPrefix}] ` @@ -68,11 +60,7 @@ export class MultiSessionConnection extends EventEmitter { // return // } - this._log.debug( - 'updating sessions count: %d -> %d', - this._sessions.length, - this._count, - ) + this._log.debug('updating sessions count: %d -> %d', this._sessions.length, this._count) // case 1 if (this._sessions.length === this._count) return @@ -108,21 +96,13 @@ export class MultiSessionConnection extends EventEmitter { this._updateSessions() if (this._connections.length === this._count) return - this._log.debug( - 'updating connections count: %d -> %d', - this._connections.length, - this._count, - ) + this._log.debug('updating connections count: %d -> %d', this._connections.length, this._count) const newEnforcePfs = this._count > 1 && this.params.isMainConnection const enforcePfsChanged = newEnforcePfs !== this._enforcePfs if (enforcePfsChanged) { - this._log.debug( - 'enforcePfs changed: %s -> %s', - this._enforcePfs, - newEnforcePfs, - ) + this._log.debug('enforcePfs changed: %s -> %s', this._enforcePfs, newEnforcePfs) this._enforcePfs = newEnforcePfs } @@ -154,9 +134,7 @@ export class MultiSessionConnection extends EventEmitter { usePfs: this.params.usePfs || this._enforcePfs, isMainConnection: this.params.isMainConnection && i === 0, withUpdates: - this.params.isMainConnection && - this.params.isMainDcConnection && - !this.params.disableUpdates, + this.params.isMainConnection && this.params.isMainDcConnection && !this.params.disableUpdates, }, session, ) @@ -174,9 +152,7 @@ export class MultiSessionConnection extends EventEmitter { conn_.onConnected() } }) - conn.on('tmp-key-change', (key, expires) => - this.emit('tmp-key-change', i, key, expires), - ) + conn.on('tmp-key-change', (key, expires) => this.emit('tmp-key-change', i, key, expires)) conn.on('auth-begin', () => { this._log.debug('received auth-begin from connection %d', i) this.emit('auth-begin', i) @@ -212,11 +188,7 @@ export class MultiSessionConnection extends EventEmitter { private _nextConnection = 0 - sendRpc( - request: T, - stack?: string, - timeout?: number, - ): Promise { + sendRpc(request: T, stack?: string, timeout?: number): Promise { // if (this.params.isMainConnection) { // find the least loaded connection let min = Infinity @@ -224,9 +196,7 @@ export class MultiSessionConnection extends EventEmitter { for (let i = 0; i < this._connections.length; i++) { const conn = this._connections[i] - const total = - conn._session.queuedRpc.length + - conn._session.pendingMessages.size() + const total = conn._session.queuedRpc.length + conn._session.pendingMessages.size() if (total < min) { min = total @@ -257,11 +227,7 @@ export class MultiSessionConnection extends EventEmitter { this.connect() } - async setAuthKey( - authKey: Buffer | null, - temp = false, - idx = 0, - ): Promise { + async setAuthKey(authKey: Buffer | null, temp = false, idx = 0): Promise { const session = this._sessions[idx] const key = temp ? session._authKeyTemp : session._authKey await key.setup(authKey) @@ -291,18 +257,14 @@ export class MultiSessionConnection extends EventEmitter { const session = this._sessions[0] if (this.params.usePfs && !session._authKeyTemp.ready) { - this._log.debug( - 'temp auth key needed but not ready, ignoring key change', - ) + this._log.debug('temp auth key needed but not ready, ignoring key change') return } if (this._sessions[0].queuedRpc.length) { // there are pending requests, we need to reconnect. - this._log.debug( - 'notifying key change on the connection due to queued rpc', - ) + this._log.debug('notifying key change on the connection due to queued rpc') this._connections[0].onConnected() } diff --git a/packages/core/src/network/network-manager.ts b/packages/core/src/network/network-manager.ts index 56965f35..c71f0dbd 100644 --- a/packages/core/src/network/network-manager.ts +++ b/packages/core/src/network/network-manager.ts @@ -3,24 +3,13 @@ import { TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime' import { ITelegramStorage } from '../storage' import { MtArgumentError, MtcuteError } from '../types' -import { - createControllablePromise, - ICryptoProvider, - Logger, - sleep, -} from '../utils' +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' -import { - defaultReconnectionStrategy, - ReconnectionStrategy, -} from './reconnection' -import { - SessionConnection, - SessionConnectionParams, -} from './session-connection' +import { defaultReconnectionStrategy, ReconnectionStrategy } from './reconnection' +import { SessionConnection, SessionConnectionParams } from './session-connection' import { defaultTransportFactory, TransportFactory } from './transports' export type ConnectionKind = 'main' | 'upload' | 'download' | 'downloadSmall' @@ -45,9 +34,7 @@ export interface NetworkManagerParams { log: Logger apiId: number - initConnectionOptions?: Partial< - Omit - > + initConnectionOptions?: Partial> transport?: TransportFactory reconnectionStrategy?: ReconnectionStrategy floodSleepThreshold: number @@ -63,17 +50,9 @@ export interface NetworkManagerParams { keepAliveAction: () => void } -export type ConnectionCountDelegate = ( - kind: ConnectionKind, - dcId: number, - isPremium: boolean -) => number +export type ConnectionCountDelegate = (kind: ConnectionKind, dcId: number, isPremium: boolean) => number -const defaultConnectionCountDelegate: ConnectionCountDelegate = ( - kind, - dcId, - isPremium, -) => { +const defaultConnectionCountDelegate: ConnectionCountDelegate = (kind, dcId, isPremium) => { switch (kind) { case 'main': return 1 @@ -185,33 +164,21 @@ export class DcConnectionManager { upload = new MultiSessionConnection( this.__baseConnectionParams(), - this.manager._connectionCount( - 'upload', - this.dcId, - this.manager.params.isPremium, - ), + this.manager._connectionCount('upload', this.dcId, this.manager.params.isPremium), this._log, 'UPLOAD', ) download = new MultiSessionConnection( this.__baseConnectionParams(), - this.manager._connectionCount( - 'download', - this.dcId, - this.manager.params.isPremium, - ), + this.manager._connectionCount('download', this.dcId, this.manager.params.isPremium), this._log, 'DOWNLOAD', ) downloadSmall = new MultiSessionConnection( this.__baseConnectionParams(), - this.manager._connectionCount( - 'downloadSmall', - this.dcId, - this.manager.params.isPremium, - ), + this.manager._connectionCount('downloadSmall', this.dcId, this.manager.params.isPremium), this._log, 'DOWNLOAD_SMALL', ) @@ -238,12 +205,7 @@ export class DcConnectionManager { mainParams.inactivityTimeout = undefined } - this.main = new MultiSessionConnection( - mainParams, - this._mainConnectionCount, - this._log, - 'MAIN', - ) + this.main = new MultiSessionConnection(mainParams, this._mainConnectionCount, this._log, 'MAIN') this._setupMulti('main') this._setupMulti('upload') @@ -258,18 +220,12 @@ export class DcConnectionManager { if (kind !== 'main') { // main connection is responsible for authorization, // and keys are then sent to other connections - this.manager._log.warn( - 'got key-change from non-main connection, ignoring', - ) + this.manager._log.warn('got key-change from non-main connection, ignoring') return } - this.manager._log.debug( - 'key change for dc %d from connection %d', - this.dcId, - idx, - ) + this.manager._log.debug('key change for dc %d from connection %d', this.dcId, idx) // send key to other connections Promise.all([ @@ -285,51 +241,35 @@ export class DcConnectionManager { }) .catch((e: Error) => this.manager.params._emitError(e)) }) - connection.on( - 'tmp-key-change', - (idx: number, key: Buffer | null, expires: number) => { - if (kind !== 'main') { - this.manager._log.warn( - 'got tmp-key-change from non-main connection, ignoring', - ) + connection.on('tmp-key-change', (idx: number, key: Buffer | null, expires: number) => { + if (kind !== 'main') { + this.manager._log.warn('got tmp-key-change from non-main connection, ignoring') - return - } + return + } - this.manager._log.debug( - 'temp key change for dc %d from connection %d', - this.dcId, - idx, - ) + this.manager._log.debug('temp key change for dc %d from connection %d', this.dcId, idx) - // send key to other connections - Promise.all([ - this.manager._storage.setTempAuthKeyFor( - this.dcId, - idx, - key, - expires * 1000, - ), - this.upload.setAuthKey(key, true), - this.download.setAuthKey(key, true), - this.downloadSmall.setAuthKey(key, true), - ]) - .then(() => { - this.upload.notifyKeyChange() - this.download.notifyKeyChange() - this.downloadSmall.notifyKeyChange() - }) - .catch((e: Error) => this.manager.params._emitError(e)) - }, - ) + // send key to other connections + Promise.all([ + this.manager._storage.setTempAuthKeyFor(this.dcId, idx, key, expires * 1000), + this.upload.setAuthKey(key, true), + this.download.setAuthKey(key, true), + this.downloadSmall.setAuthKey(key, true), + ]) + .then(() => { + this.upload.notifyKeyChange() + this.download.notifyKeyChange() + this.downloadSmall.notifyKeyChange() + }) + .catch((e: Error) => this.manager.params._emitError(e)) + }) connection.on('auth-begin', () => { // we need to propagate auth-begin to all connections // to avoid them sending requests before auth is complete if (kind !== 'main') { - this.manager._log.warn( - 'got auth-begin from non-main connection, ignoring', - ) + this.manager._log.warn('got auth-begin from non-main connection, ignoring') return } @@ -357,22 +297,14 @@ export class DcConnectionManager { if (isPrimary) { this.main.setInactivityTimeout(undefined) } else { - this.main.setInactivityTimeout( - this.manager.params.inactivityTimeout ?? 60_000, - ) + this.main.setInactivityTimeout(this.manager.params.inactivityTimeout ?? 60_000) } } setIsPremium(isPremium: boolean): void { - this.upload.setCount( - this.manager._connectionCount('upload', this.dcId, isPremium), - ) - this.download.setCount( - this.manager._connectionCount('download', this.dcId, isPremium), - ) - this.downloadSmall.setCount( - this.manager._connectionCount('downloadSmall', this.dcId, isPremium), - ) + this.upload.setCount(this.manager._connectionCount('upload', this.dcId, isPremium)) + this.download.setCount(this.manager._connectionCount('download', this.dcId, isPremium)) + this.downloadSmall.setCount(this.manager._connectionCount('downloadSmall', this.dcId, isPremium)) } async loadKeys(): Promise { @@ -392,10 +324,7 @@ export class DcConnectionManager { if (this.manager.params.usePfs) { await Promise.all( this.main._sessions.map(async (_, i) => { - const temp = await this.manager._storage.getAuthKeyFor( - this.dcId, - i, - ) + const temp = await this.manager._storage.getAuthKeyFor(this.dcId, i) await this.main.setAuthKey(temp, true, i) if (i === 0) { @@ -429,10 +358,7 @@ export class NetworkManager { private _lastUpdateTime = 0 private _updateHandler: (upd: tl.TypeUpdates) => void = () => {} - constructor( - readonly params: NetworkManagerParams & NetworkManagerExtraParams, - readonly config: ConfigManager, - ) { + constructor(readonly params: NetworkManagerParams & NetworkManagerExtraParams, readonly config: ConfigManager) { let deviceModel = 'mtcute on ' let appVersion = 'unknown' if (typeof process !== 'undefined' && typeof require !== 'undefined') { @@ -442,15 +368,12 @@ export class NetworkManager { try { // for production builds - appVersion = (require('../package.json') as { version: string }) - .version + appVersion = (require('../package.json') as { version: string }).version } catch (e) { try { // for development builds (additional /src/ in path) - appVersion = ( - require('../../package.json') as { version: string } - ).version + appVersion = (require('../../package.json') as { version: string }).version } catch (e) {} } } else if (typeof navigator !== 'undefined') { @@ -472,18 +395,14 @@ export class NetworkManager { } this._transportFactory = params.transport ?? defaultTransportFactory - this._reconnectionStrategy = - params.reconnectionStrategy ?? defaultReconnectionStrategy - this._connectionCount = - params.connectionCount ?? defaultConnectionCountDelegate + this._reconnectionStrategy = params.reconnectionStrategy ?? defaultReconnectionStrategy + this._connectionCount = params.connectionCount ?? defaultConnectionCountDelegate this._onConfigChanged = this._onConfigChanged.bind(this) config.onConfigUpdate(this._onConfigChanged) } - private async _findDcOptions( - dcId: number, - ): Promise { + private async _findDcOptions(dcId: number): Promise { const main = await this.config.findOption({ dcId, allowIpv6: this.params.useIpv6, @@ -633,11 +552,7 @@ export class NetworkManager { promise.resolve() delete this._pendingExports[manager.dcId] } catch (e) { - this._log.warn( - 'failed to export auth to dc %d: %s', - manager.dcId, - e, - ) + this._log.warn('failed to export auth to dc %d: %s', manager.dcId, e) promise.reject(e) throw e } @@ -655,10 +570,7 @@ export class NetworkManager { // future-proofing. should probably remove once the implementation is stable // eslint-disable-next-line @typescript-eslint/require-await async notifyLoggedIn(auth: tl.auth.TypeAuthorization): Promise { - if ( - auth._ === 'auth.authorizationSignUpRequired' || - auth.user._ === 'userEmpty' - ) { + if (auth._ === 'auth.authorizationSignUpRequired' || auth.user._ === 'userEmpty') { return } @@ -693,10 +605,7 @@ export class NetworkManager { const options = await this._findDcOptions(newDc) if (!this._dcConnections.has(newDc)) { - this._dcConnections.set( - newDc, - new DcConnectionManager(this, newDc, options), - ) + this._dcConnections.set(newDc, new DcConnectionManager(this, newDc, options)) } await this._storage.setDefaultDcs(options) @@ -714,8 +623,7 @@ export class NetworkManager { throw new MtcuteError('Not connected to any DC') } - const floodSleepThreshold = - params?.floodSleepThreshold ?? this.params.floodSleepThreshold + const floodSleepThreshold = params?.floodSleepThreshold ?? this.params.floodSleepThreshold const maxRetryCount = params?.maxRetryCount ?? this.params.maxRetryCount // do not send requests that are in flood wait @@ -729,10 +637,7 @@ export class NetworkManager { await sleep(delta) this._floodWaitedRequests.delete(message._) } else { - const err = tl.RpcError.create( - tl.RpcError.FLOOD, - 'FLOOD_WAIT_%d', - ) + const err = tl.RpcError.create(tl.RpcError.FLOOD, 'FLOOD_WAIT_%d') err.seconds = Math.ceil(delta / 1000) throw err } @@ -770,11 +675,7 @@ export class NetworkManager { if (!tl.RpcError.is(e)) continue if (!(e.code in CLIENT_ERRORS)) { - this._log.warn( - 'Telegram is having internal issues: %d %s, retrying', - e.code, - e.message, - ) + this._log.warn('Telegram is having internal issues: %d %s, retrying', e.code, e.message) if (e.text === 'WORKER_BUSY_TOO_LONG_RETRY') { // according to tdlib, "it is dangerous to resend query without timeout, so use 1" @@ -783,17 +684,10 @@ export class NetworkManager { continue } - if ( - e.is('FLOOD_WAIT_%d') || - e.is('SLOWMODE_WAIT_%d') || - e.is('FLOOD_TEST_PHONE_WAIT_%d') - ) { + if (e.is('FLOOD_WAIT_%d') || e.is('SLOWMODE_WAIT_%d') || e.is('FLOOD_TEST_PHONE_WAIT_%d')) { if (e.text !== 'SLOWMODE_WAIT_%d') { // SLOW_MODE_WAIT is chat-specific, not request-specific - this._floodWaitedRequests.set( - message._, - Date.now() + e.seconds * 1000, - ) + this._floodWaitedRequests.set(message._, Date.now() + e.seconds * 1000) } // In test servers, FLOOD_WAIT_0 has been observed, and sleeping for @@ -810,11 +704,7 @@ export class NetworkManager { } if (manager === this._primaryDc) { - if ( - e.is('PHONE_MIGRATE_%d') || - e.is('NETWORK_MIGRATE_%d') || - e.is('USER_MIGRATE_%d') - ) { + if (e.is('PHONE_MIGRATE_%d') || e.is('NETWORK_MIGRATE_%d') || e.is('USER_MIGRATE_%d')) { this._log.info('Migrate error, new dc = %d', e.newDc) await this.changePrimaryDc(e.newDc) @@ -825,9 +715,7 @@ export class NetworkManager { } } else if (e.is('AUTH_KEY_UNREGISTERED')) { // we can try re-exporting auth from the primary connection - this._log.warn( - 'exported auth key error, trying re-exporting..', - ) + this._log.warn('exported auth key error, trying re-exporting..') await this._exportAuthTo(manager) continue @@ -863,11 +751,7 @@ export class NetworkManager { // guess based on the provided delegate. it is most likely correct, // but we should give actual values if possible - return this._connectionCount( - kind, - dcId ?? this._primaryDc.dcId, - this.params.isPremium, - ) + return this._connectionCount(kind, dcId ?? this._primaryDc.dcId, this.params.isPremium) } return dc[kind].getPoolSize() diff --git a/packages/core/src/network/persistent-connection.ts b/packages/core/src/network/persistent-connection.ts index 23c57882..9cef4d72 100644 --- a/packages/core/src/network/persistent-connection.ts +++ b/packages/core/src/network/persistent-connection.ts @@ -5,11 +5,7 @@ import { tl } from '@mtcute/tl' import { MtcuteError } from '../types' import { ICryptoProvider, Logger } from '../utils' import { ReconnectionStrategy } from './reconnection' -import { - ITelegramTransport, - TransportFactory, - TransportState, -} from './transports' +import { ITelegramTransport, TransportFactory, TransportState } from './transports' export interface PersistentConnectionParams { crypto: ICryptoProvider @@ -54,10 +50,7 @@ export abstract class PersistentConnection extends EventEmitter { protected abstract onMessage(data: Buffer): void - protected constructor( - params: PersistentConnectionParams, - readonly log: Logger, - ) { + protected constructor(params: PersistentConnectionParams, readonly log: Logger) { super() this.params = params this.changeTransport(params.transportFactory) @@ -169,7 +162,9 @@ export abstract class PersistentConnection extends EventEmitter { if (this.isConnected) { throw new MtcuteError('Connection is already opened!') } - if (this._destroyed) { throw new MtcuteError('Connection is already destroyed!') } + if (this._destroyed) { + throw new MtcuteError('Connection is already destroyed!') + } if (this._reconnectionTimeout != null) { clearTimeout(this._reconnectionTimeout) @@ -199,17 +194,11 @@ export abstract class PersistentConnection extends EventEmitter { protected _rescheduleInactivity(): void { if (!this.params.inactivityTimeout) return if (this._inactivityTimeout) clearTimeout(this._inactivityTimeout) - this._inactivityTimeout = setTimeout( - this._onInactivityTimeout, - this.params.inactivityTimeout, - ) + this._inactivityTimeout = setTimeout(this._onInactivityTimeout, this.params.inactivityTimeout) } protected _onInactivityTimeout(): void { - this.log.info( - 'disconnected because of inactivity for %d', - this.params.inactivityTimeout, - ) + this.log.info('disconnected because of inactivity for %d', this.params.inactivityTimeout) this._inactive = true this._inactivityTimeout = null this._transport.close() diff --git a/packages/core/src/network/reconnection.ts b/packages/core/src/network/reconnection.ts index 49b1a0a9..c289a133 100644 --- a/packages/core/src/network/reconnection.ts +++ b/packages/core/src/network/reconnection.ts @@ -7,7 +7,7 @@ export type ReconnectionStrategy = ( params: T, lastError: Error | null, consequentFails: number, - previousWait: number | null + previousWait: number | null, ) => number | false /** diff --git a/packages/core/src/network/session-connection.ts b/packages/core/src/network/session-connection.ts index 8cd1796b..a838a1c8 100644 --- a/packages/core/src/network/session-connection.ts +++ b/packages/core/src/network/session-connection.ts @@ -3,13 +3,7 @@ import Long from 'long' import { mtp, tl } from '@mtcute/tl' -import { - TlBinaryReader, - TlBinaryWriter, - TlReaderMap, - TlSerializationCounter, - TlWriterMap, -} from '@mtcute/tl-runtime' +import { TlBinaryReader, TlBinaryWriter, TlReaderMap, TlSerializationCounter, TlWriterMap } from '@mtcute/tl-runtime' import { gzipDeflate, gzipInflate } from '@mtcute/tl-runtime/src/platform/gzip' import { MtArgumentError, MtcuteError, MtTimeoutError } from '../types' @@ -26,10 +20,7 @@ import { import { createAesIgeForMessageOld } from '../utils/crypto/mtproto' import { doAuthorization } from './authorization' import { MtprotoSession, PendingMessage, PendingRpc } from './mtproto-session' -import { - PersistentConnection, - PersistentConnectionParams, -} from './persistent-connection' +import { PersistentConnection, PersistentConnectionParams } from './persistent-connection' import { TransportError } from './transports' const TEMP_AUTH_KEY_EXPIRY = 86400 @@ -53,9 +44,10 @@ export interface SessionConnectionParams extends PersistentConnectionParams { // const DESTROY_AUTH_KEY = Buffer.from('605134d1', 'hex') function makeNiceStack(error: tl.RpcError, stack: string, method?: string) { - error.stack = `RpcError (${error.code} ${error.text}): ${ - error.message - }\n at ${method}\n${stack.split('\n').slice(2).join('\n')}` + error.stack = `RpcError (${error.code} ${error.text}): ${error.message}\n at ${method}\n${stack + .split('\n') + .slice(2) + .join('\n')}` } /** @@ -68,10 +60,7 @@ export class SessionConnection extends PersistentConnection { private _queuedDestroySession: Long[] = [] // waitForMessage - private _pendingWaitForUnencrypted: [ - ControllablePromise, - NodeJS.Timeout - ][] = [] + private _pendingWaitForUnencrypted: [ControllablePromise, NodeJS.Timeout][] = [] private _usePfs = this.params.usePfs ?? false private _isPfsBindingPending = false @@ -83,10 +72,7 @@ export class SessionConnection extends PersistentConnection { private _readerMap: TlReaderMap private _writerMap: TlWriterMap - constructor( - params: SessionConnectionParams, - readonly _session: MtprotoSession, - ) { + constructor(params: SessionConnectionParams, readonly _session: MtprotoSession) { super(params, _session.log.create('conn')) this._flushTimer.onTimeout(this._flush.bind(this)) @@ -122,12 +108,10 @@ export class SessionConnection extends PersistentConnection { onTransportClose(): void { super.onTransportClose() - Object.values(this._pendingWaitForUnencrypted).forEach( - ([prom, timeout]) => { - prom.reject(new MtcuteError('Connection closed')) - clearTimeout(timeout) - }, - ) + Object.values(this._pendingWaitForUnencrypted).forEach(([prom, timeout]) => { + prom.reject(new MtcuteError('Connection closed')) + clearTimeout(timeout) + }) this.emit('disconnect') @@ -186,10 +170,7 @@ export class SessionConnection extends PersistentConnection { // forgetting our temp key (which is kinda weird but expected) if (this._usePfs) { - if ( - !this._isPfsBindingPending && - this._session._authKeyTemp.ready - ) { + if (!this._isPfsBindingPending && this._session._authKeyTemp.ready) { this.log.info('transport error 404, reauthorizing pfs') // this is important! we must reset temp auth key before @@ -206,9 +187,7 @@ export class SessionConnection extends PersistentConnection { return } else if (this._isPfsBindingPending) { - this.log.info( - 'transport error 404, pfs binding in progress', - ) + this.log.info('transport error 404, pfs binding in progress') this._onAllFailed('temp key expired, binding pending') @@ -232,9 +211,7 @@ export class SessionConnection extends PersistentConnection { this._onAllFailed(`transport error ${error.code}`) if (error.code === 429) { - this._session.onTransportFlood( - this.emit.bind(this, 'flood-done'), - ) + this._session.onTransportFlood(this.emit.bind(this, 'flood-done')) return } @@ -250,10 +227,7 @@ export class SessionConnection extends PersistentConnection { // we must send some user-related rpc to the server to make sure that // it will send us updates this.sendRpc({ _: 'updates.getState' }).catch((err: any) => { - this.log.warn( - 'failed to send updates.getState: %s', - err.text || err.message, - ) + this.log.warn('failed to send updates.getState: %s', err.text || err.message) }) } @@ -329,9 +303,7 @@ export class SessionConnection extends PersistentConnection { doAuthorization(this, this.params.crypto, TEMP_AUTH_KEY_EXPIRY) .then(async ([tempAuthKey, tempServerSalt]) => { if (!this._usePfs) { - this.log.info( - 'pfs has been disabled while generating temp key', - ) + this.log.info('pfs has been disabled while generating temp key') return } @@ -355,8 +327,7 @@ export class SessionConnection extends PersistentConnection { tempAuthKeyId: longFromBuffer(tempKey.id), permAuthKeyId: longFromBuffer(this._session._authKey.id), tempSessionId: this._session._sessionId, - expiresAt: - Math.floor(Date.now() / 1000) + TEMP_AUTH_KEY_EXPIRY, + expiresAt: Math.floor(Date.now() / 1000) + TEMP_AUTH_KEY_EXPIRY, } // encrypt using mtproto v1 (fucking kill me plz) @@ -384,15 +355,9 @@ export class SessionConnection extends PersistentConnection { true, ) const encryptedData = await ige.encrypt(msgWithPadding) - const encryptedMessage = Buffer.concat([ - this._session._authKey.id, - msgKey, - encryptedData, - ]) + const encryptedMessage = Buffer.concat([this._session._authKey.id, msgKey, encryptedData]) - const promise = createControllablePromise< - mtp.RawMt_rpc_error | boolean - >() + const promise = createControllablePromise() // encrypt the message using temp key and same msg id // this is a bit of a hack, but it works @@ -418,14 +383,8 @@ export class SessionConnection extends PersistentConnection { expiresAt: inner.expiresAt, encryptedMessage, } - const reqSize = TlSerializationCounter.countNeededBytes( - this._writerMap, - request, - ) - const reqWriter = TlBinaryWriter.alloc( - this._writerMap, - reqSize + 16, - ) + const reqSize = TlSerializationCounter.countNeededBytes(this._writerMap, request) + const reqWriter = TlBinaryWriter.alloc(this._writerMap, reqSize + 16) reqWriter.long(this._registerOutgoingMsgId(msgId)) reqWriter.uint(this._session.getSeqNo()) reqWriter.uint(reqSize) @@ -444,19 +403,13 @@ export class SessionConnection extends PersistentConnection { this._session.pendingMessages.delete(msgId) if (!this._usePfs) { - this.log.info( - 'pfs has been disabled while binding temp key', - ) + this.log.info('pfs has been disabled while binding temp key') return } if (typeof res === 'object') { - this.log.error( - 'failed to bind temp key: %s:%s', - res.errorCode, - res.errorMessage, - ) + this.log.error('failed to bind temp key: %s:%s', res.errorCode, res.errorMessage) throw new MtcuteError('Failed to bind temporary key') } @@ -467,10 +420,7 @@ export class SessionConnection extends PersistentConnection { this._session._authKeyTemp = tempKey this._session.serverSalt = tempServerSalt - this.log.debug( - 'temp key has been bound, exp = %d', - inner.expiresAt, - ) + this.log.debug('temp key has been bound, exp = %d', inner.expiresAt) this._isPfsBindingPending = false this._isPfsBindingPendingInBackground = false @@ -508,10 +458,7 @@ export class SessionConnection extends PersistentConnection { const promise = createControllablePromise() const timeoutId = setTimeout(() => { promise.reject(new MtTimeoutError(timeout)) - this._pendingWaitForUnencrypted = - this._pendingWaitForUnencrypted.filter( - (it) => it[0] !== promise, - ) + this._pendingWaitForUnencrypted = this._pendingWaitForUnencrypted.filter((it) => it[0] !== promise) }, timeout) this._pendingWaitForUnencrypted.push([promise, timeoutId]) @@ -523,14 +470,11 @@ export class SessionConnection extends PersistentConnection { // auth_key_id = 0, meaning it's an unencrypted message used for authorization if (this._pendingWaitForUnencrypted.length) { - const [promise, timeout] = - this._pendingWaitForUnencrypted.shift()! + const [promise, timeout] = this._pendingWaitForUnencrypted.shift()! clearTimeout(timeout) promise.resolve(data) } else { - this.log.debug( - 'unencrypted message received, but no one is waiting for it', - ) + this.log.debug('unencrypted message received, but no one is waiting for it') } return @@ -552,11 +496,7 @@ export class SessionConnection extends PersistentConnection { } } - private _handleRawMessage( - messageId: Long, - seqNo: number, - message: TlBinaryReader, - ): void { + private _handleRawMessage(messageId: Long, seqNo: number, message: TlBinaryReader): void { if (message.peekUint() === 0x3072cfa1) { // gzip_packed // we can't use message.gzip() because it may contain msg_container, @@ -566,10 +506,7 @@ export class SessionConnection extends PersistentConnection { return this._handleRawMessage( messageId, seqNo, - new TlBinaryReader( - this._readerMap, - gzipInflate(message.bytes()), - ), + new TlBinaryReader(this._readerMap, gzipInflate(message.bytes())), ) } @@ -587,11 +524,7 @@ export class SessionConnection extends PersistentConnection { // container can't contain other containers, but can contain rpc_result const obj = message.raw(length) - this._handleRawMessage( - msgId, - seqNo, - new TlBinaryReader(this._readerMap, obj), - ) + this._handleRawMessage(msgId, seqNo, new TlBinaryReader(this._readerMap, obj)) } return @@ -610,10 +543,7 @@ export class SessionConnection extends PersistentConnection { private _handleMessage(messageId: Long, message_: unknown): void { if (messageId.isEven()) { - this.log.warn( - 'warn: ignoring message with invalid messageId = %s (is even)', - messageId, - ) + this.log.warn('warn: ignoring message with invalid messageId = %s (is even)', messageId) return } @@ -662,11 +592,7 @@ export class SessionConnection extends PersistentConnection { this._onMessagesInfo(message.msgIds, message.info) break case 'mt_msg_detailed_info': - this._onMessageInfo( - message.msgId, - message.status, - message.answerMsgId, - ) + this._onMessageInfo(message.msgId, message.status, message.answerMsgId) break case 'mt_msg_new_detailed_info': this._onMessageInfo(Long.ZERO, 0, message.answerMsgId) @@ -680,12 +606,7 @@ export class SessionConnection extends PersistentConnection { case 'mt_msgs_state_req': case 'mt_msg_resend_req': // tdlib doesnt handle them, so why should we? :upside_down_face: - this.log.warn( - 'received %s (msg_id = %l): %j', - message._, - messageId, - message, - ) + this.log.warn('received %s (msg_id = %l): %j', message._, messageId, message) break case 'mt_destroy_session_ok': case 'mt_destroy_session_none': @@ -700,9 +621,7 @@ export class SessionConnection extends PersistentConnection { this.log.verbose('<<< %j', message) if (this.params.disableUpdates) { - this.log.warn( - 'received updates, but updates are disabled', - ) + this.log.warn('received updates, but updates are disabled') // likely due to some request in the session missing invokeWithoutUpdates break } @@ -732,10 +651,7 @@ export class SessionConnection extends PersistentConnection { } catch (err) { resultType = message.peekUint() } - this.log.warn( - 'received rpc_result with %j with req_msg_id = 0', - resultType, - ) + this.log.warn('received rpc_result with %j with req_msg_id = 0', resultType) return } @@ -754,17 +670,9 @@ export class SessionConnection extends PersistentConnection { // check if the msg is one of the recent ones if (this._session.recentOutgoingMsgIds.has(reqMsgId)) { - this.log.debug( - 'received rpc_result again for %l (contains %j)', - reqMsgId, - result, - ) + this.log.debug('received rpc_result again for %l (contains %j)', reqMsgId, result) } else { - this.log.warn( - 'received rpc_result for unknown message %l: %j', - reqMsgId, - result, - ) + this.log.warn('received rpc_result for unknown message %l: %j', reqMsgId, result) } return @@ -781,11 +689,7 @@ export class SessionConnection extends PersistentConnection { return } - this.log.error( - 'received rpc_result for %s request %l', - msg._, - reqMsgId, - ) + this.log.error('received rpc_result for %s request %l', msg._, reqMsgId) return } @@ -793,9 +697,7 @@ export class SessionConnection extends PersistentConnection { const rpc = msg.rpc const customReader = this._readerMap._results![rpc.method] - const result: any = customReader ? - customReader(message) : - message.object() + const result: any = customReader ? customReader(message) : message.object() // initConnection call was definitely received and // processed by the server, so we no longer need to use it @@ -841,15 +743,10 @@ export class SessionConnection extends PersistentConnection { // is already serialized, so we do this awesome hack this.sendRpc({ _: 'help.getNearestDc' }) .then(() => { - this.log.debug( - 'additional help.getNearestDc for initConnection ok', - ) + this.log.debug('additional help.getNearestDc for initConnection ok') }) .catch((err) => { - this.log.debug( - 'additional help.getNearestDc for initConnection error: %s', - err, - ) + this.log.debug('additional help.getNearestDc for initConnection error: %s', err) }) return @@ -865,12 +762,7 @@ export class SessionConnection extends PersistentConnection { rpc.promise.reject(error) } else { - this.log.debug( - 'received rpc_result (%s) for request %l (%s)', - result._, - reqMsgId, - rpc.method, - ) + this.log.debug('received rpc_result (%s) for request %l (%s)', result._, reqMsgId, rpc.method) if (rpc.cancelled) return @@ -894,11 +786,7 @@ export class SessionConnection extends PersistentConnection { switch (msg._) { case 'container': - this.log.debug( - 'received ack for container %l (size = %d)', - msgId, - msg.msgIds.length, - ) + this.log.debug('received ack for container %l (size = %d)', msgId, msg.msgIds.length) msg.msgIds.forEach((msgId) => this._onMessageAcked(msgId, true)) @@ -908,20 +796,11 @@ export class SessionConnection extends PersistentConnection { case 'rpc': { const rpc = msg.rpc - this.log.debug( - 'received ack for rpc query %l (%s, acked before = %s)', - msgId, - rpc.method, - rpc.acked, - ) + this.log.debug('received ack for rpc query %l (%s, acked before = %s)', msgId, rpc.method, rpc.acked) rpc.acked = true - if ( - !inContainer && - rpc.containerId && - this._session.pendingMessages.has(rpc.containerId) - ) { + if (!inContainer && rpc.containerId && this._session.pendingMessages.has(rpc.containerId)) { // ack all the messages in that container this._onMessageAcked(rpc.containerId) } @@ -940,11 +819,7 @@ export class SessionConnection extends PersistentConnection { default: if (!inContainer) { - this.log.warn( - 'received unexpected ack for %s query %l', - msg._, - msgId, - ) + this.log.warn('received unexpected ack for %s query %l', msg._, msgId) } } } @@ -973,64 +848,36 @@ export class SessionConnection extends PersistentConnection { } } - private _onMessageFailed( - msgId: Long, - reason: string, - inContainer = false, - ): void { + private _onMessageFailed(msgId: Long, reason: string, inContainer = false): void { const msgInfo = this._session.pendingMessages.get(msgId) if (!msgInfo) { - this.log.debug( - 'unknown message %l failed because of %s', - msgId, - reason, - ) + this.log.debug('unknown message %l failed because of %s', msgId, reason) return } switch (msgInfo._) { case 'container': - this.log.debug( - 'container %l (size = %d) failed because of %s', - msgId, - msgInfo.msgIds.length, - reason, - ) - msgInfo.msgIds.forEach((msgId) => - this._onMessageFailed(msgId, reason, true), - ) + this.log.debug('container %l (size = %d) failed because of %s', msgId, msgInfo.msgIds.length, reason) + msgInfo.msgIds.forEach((msgId) => this._onMessageFailed(msgId, reason, true)) break case 'ping': - this.log.debug( - 'ping (msg_id = %l) failed because of %s', - msgId, - reason, - ) + this.log.debug('ping (msg_id = %l) failed because of %s', msgId, reason) // restart ping this._session.resetLastPing(true) break case 'rpc': { const rpc = msgInfo.rpc - this.log.debug( - 'rpc query %l (%s) failed because of %s', - msgId, - rpc.method, - reason, - ) + this.log.debug('rpc query %l (%s) failed because of %s', msgId, rpc.method, reason) // since the query was rejected, we can let it reassign msg_id to avoid containers this._session.pendingMessages.delete(msgId) rpc.msgId = undefined this._enqueueRpc(rpc, true) - if ( - !inContainer && - rpc.containerId && - this._session.pendingMessages.has(rpc.containerId) - ) { + if (!inContainer && rpc.containerId && this._session.pendingMessages.has(rpc.containerId)) { // fail all the messages in that container this._onMessageFailed(rpc.containerId, reason) } @@ -1066,11 +913,7 @@ export class SessionConnection extends PersistentConnection { this._flushTimer.emitWhenIdle() break case 'bind': - this.log.debug( - 'temp key binding request %l failed because of %s, retrying', - msgId, - reason, - ) + this.log.debug('temp key binding request %l failed because of %s, retrying', msgId, reason) msgInfo.promise.reject(Error(reason)) } @@ -1087,33 +930,19 @@ export class SessionConnection extends PersistentConnection { const info = this._session.pendingMessages.get(msgId) if (!info) { - this.log.warn( - 'received pong to unknown ping (msg_id %l, ping_id %l)', - msgId, - pingId, - ) + this.log.warn('received pong to unknown ping (msg_id %l, ping_id %l)', msgId, pingId) return } if (info._ !== 'ping') { - this.log.warn( - 'received pong to %s query, not ping (msg_id %l, ping_id %l)', - info._, - msgId, - pingId, - ) + this.log.warn('received pong to %s query, not ping (msg_id %l, ping_id %l)', info._, msgId, pingId) return } if (info.pingId.neq(pingId)) { - this.log.warn( - 'received pong to %l, but expected ping_id = %l (got %l)', - msgId, - info.pingId, - pingId, - ) + this.log.warn('received pong to %l, but expected ping_id = %l (got %l)', msgId, info.pingId, pingId) } const rtt = Date.now() - this._session.lastPingTime @@ -1123,12 +952,7 @@ export class SessionConnection extends PersistentConnection { this._onMessageAcked(info.containerId) } - this.log.debug( - 'received pong: msg_id %l, ping_id %l, rtt = %dms', - msgId, - pingId, - rtt, - ) + this.log.debug('received pong: msg_id %l, ping_id %l, rtt = %dms', msgId, pingId, rtt) this._session.resetLastPing() } @@ -1138,10 +962,7 @@ export class SessionConnection extends PersistentConnection { this._onMessageFailed(msg.badMsgId, 'bad_server_salt') } - private _onBadMsgNotification( - msgId: Long, - msg: mtp.RawMt_bad_msg_notification, - ): void { + private _onBadMsgNotification(msgId: Long, msg: mtp.RawMt_bad_msg_notification): void { switch (msg.errorCode) { case 16: case 17: @@ -1151,21 +972,13 @@ export class SessionConnection extends PersistentConnection { // code 20 means msg_id is too old, // we just need to resend the message const serverTime = msgId.low >>> 0 - const timeOffset = - Math.floor(Date.now() / 1000) - serverTime + const timeOffset = Math.floor(Date.now() / 1000) - serverTime this._session._timeOffset = timeOffset - this.log.debug( - 'server time: %d, corrected offset to %d', - serverTime, - timeOffset, - ) + this.log.debug('server time: %d, corrected offset to %d', serverTime, timeOffset) } - this._onMessageFailed( - msg.badMsgId, - `bad_msg_notification ${msg.errorCode}`, - ) + this._onMessageFailed(msg.badMsgId, `bad_msg_notification ${msg.errorCode}`) break } default: @@ -1180,24 +993,14 @@ export class SessionConnection extends PersistentConnection { } } - private _onNewSessionCreated({ - firstMsgId, - serverSalt, - uniqueId, - }: mtp.RawMt_new_session_created): void { + private _onNewSessionCreated({ firstMsgId, serverSalt, uniqueId }: mtp.RawMt_new_session_created): void { if (uniqueId.eq(this._session.lastSessionCreatedUid)) { - this.log.debug( - 'received new_session_created with the same uid = %l, ignoring', - uniqueId, - ) + this.log.debug('received new_session_created with the same uid = %l, ignoring', uniqueId) return } - if ( - !this._session.lastSessionCreatedUid.isZero() && - !this.params.disableUpdates - ) { + if (!this._session.lastSessionCreatedUid.isZero() && !this.params.disableUpdates) { // force the client to fetch missed updates // when _lastSessionCreatedUid == 0, the connection has // just been established, and the client will fetch them anyways @@ -1206,11 +1009,7 @@ export class SessionConnection extends PersistentConnection { this._session.serverSalt = serverSalt - this.log.debug( - 'received new_session_created, uid = %l, first msg_id = %l', - uniqueId, - firstMsgId, - ) + this.log.debug('received new_session_created, uid = %l, first msg_id = %l', uniqueId, firstMsgId) for (const msgId of this._session.pendingMessages.keys()) { const val = this._session.pendingMessages.get(msgId)! @@ -1233,8 +1032,7 @@ export class SessionConnection extends PersistentConnection { return } - const containerId = - val._ === 'rpc' ? val.rpc.containerId || msgId : val.containerId + const containerId = val._ === 'rpc' ? val.rpc.containerId || msgId : val.containerId if (containerId.lt(firstMsgId)) { this._onMessageFailed(msgId, 'new_session_created', true) @@ -1242,20 +1040,13 @@ export class SessionConnection extends PersistentConnection { } } - private _onMessageInfo( - msgId: Long, - status: number, - answerMsgId: Long, - ): void { + private _onMessageInfo(msgId: Long, status: number, answerMsgId: Long): void { if (!msgId.isZero()) { const info = this._session.pendingMessages.get(msgId) if (!info) { if (!this._session.recentOutgoingMsgIds.has(msgId)) { - this.log.warn( - 'received message info about unknown message %l', - msgId, - ) + this.log.warn('received message info about unknown message %l', msgId) } return @@ -1278,10 +1069,7 @@ export class SessionConnection extends PersistentConnection { answerMsgId, ) - return this._onMessageFailed( - msgId, - 'message info state = 0, ans_id = 0', - ) + return this._onMessageFailed(msgId, 'message info state = 0, ans_id = 0') } // fallthrough case 4: @@ -1290,33 +1078,20 @@ export class SessionConnection extends PersistentConnection { } } - if ( - !answerMsgId.isZero() && - !this._session.recentIncomingMsgIds.has(answerMsgId) - ) { - this.log.debug( - 'received message info for %l, but answer (%l) was not received yet', - msgId, - answerMsgId, - ) + if (!answerMsgId.isZero() && !this._session.recentIncomingMsgIds.has(answerMsgId)) { + this.log.debug('received message info for %l, but answer (%l) was not received yet', msgId, answerMsgId) this._session.queuedResendReq.push(answerMsgId) this._flushTimer.emitWhenIdle() return } - this.log.debug( - 'received message info for %l, and answer (%l) was already received', - msgId, - answerMsgId, - ) + this.log.debug('received message info for %l, and answer (%l) was already received', msgId, answerMsgId) } private _onMessagesInfo(msgIds: Long[], info: Buffer): void { if (msgIds.length !== info.length) { - this.log.warn( - 'messages state info was invalid: msg_ids.length !== info.length', - ) + this.log.warn('messages state info was invalid: msg_ids.length !== info.length') } for (let i = 0; i < msgIds.length; i++) { @@ -1328,20 +1103,13 @@ export class SessionConnection extends PersistentConnection { const info = this._session.pendingMessages.get(msg.reqMsgId) if (!info) { - this.log.warn( - 'received msgs_state_info to unknown request %l', - msg.reqMsgId, - ) + this.log.warn('received msgs_state_info to unknown request %l', msg.reqMsgId) return } if (info._ !== 'state') { - this.log.warn( - 'received msgs_state_info to %s query %l', - info._, - msg.reqMsgId, - ) + this.log.warn('received msgs_state_info to %s query %l', info._, msg.reqMsgId) return } @@ -1350,16 +1118,10 @@ export class SessionConnection extends PersistentConnection { } private _onDestroySessionResult(msg: mtp.TypeDestroySessionRes): void { - const reqMsgId = this._session.destroySessionIdToMsgId.get( - msg.sessionId, - ) + const reqMsgId = this._session.destroySessionIdToMsgId.get(msg.sessionId) if (!reqMsgId) { - this.log.warn( - 'received %s for unknown session %h', - msg._, - msg.sessionId, - ) + this.log.warn('received %s for unknown session %h', msg._, msg.sessionId) return } @@ -1397,11 +1159,7 @@ export class SessionConnection extends PersistentConnection { } } - sendRpc( - request: T, - stack?: string, - timeout?: number, - ): Promise { + sendRpc(request: T, stack?: string, timeout?: number): Promise { if (this._usable && this.params.inactivityTimeout) { this._rescheduleInactivity() } @@ -1427,11 +1185,7 @@ export class SessionConnection extends PersistentConnection { // until some of the requests wrapped with it is // either acked or returns rpc_result - this.log.debug( - 'wrapping %s with initConnection, layer: %d', - method, - this.params.layer, - ) + this.log.debug('wrapping %s with initConnection, layer: %d', method, this.params.layer) const proxy = this._transport.getMtproxyInfo?.() obj = { _: 'invokeWithLayer', @@ -1454,9 +1208,7 @@ 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 MtArgumentError( - `Payload is too big (${content.length} > 1044404)`, - ) + throw new MtArgumentError(`Payload is too big (${content.length} > 1044404)`) } // gzip @@ -1467,10 +1219,7 @@ export class SessionConnection extends PersistentConnection { // if it is less than 0.9, then try to compress the whole request const middle = ~~((content.length - 1024) / 2) - const gzipped = gzipDeflate( - content.slice(middle, middle + 1024), - 0.9, - ) + const gzipped = gzipDeflate(content.slice(middle, middle + 1024), 0.9) if (!gzipped) shouldGzip = false } @@ -1479,12 +1228,7 @@ export class SessionConnection extends PersistentConnection { const gzipped = gzipDeflate(content, 0.9) if (gzipped) { - this.log.debug( - 'gzipped %s (%db -> %db)', - method, - content.length, - gzipped.length, - ) + this.log.debug('gzipped %s (%db -> %db)', method, content.length, gzipped.length) content = gzipped } else { @@ -1499,9 +1243,7 @@ export class SessionConnection extends PersistentConnection { data: content, stack, // we will need to know size of gzip_packed overhead in _flush() - gzipOverhead: shouldGzip ? - 4 + TlSerializationCounter.countBytesOverhead(content.length) : - 0, + gzipOverhead: shouldGzip ? 4 + TlSerializationCounter.countBytesOverhead(content.length) : 0, initConn, // setting them as well so jit can optimize stuff @@ -1515,18 +1257,11 @@ export class SessionConnection extends PersistentConnection { timeout: undefined, } - const promise = createCancellablePromise( - this._cancelRpc.bind(this, pending), - ) + const promise = createCancellablePromise(this._cancelRpc.bind(this, pending)) pending.promise = promise if (timeout) { - pending.timeout = setTimeout( - this._cancelRpc, - timeout, - pending, - true, - ) + pending.timeout = setTimeout(this._cancelRpc, timeout, pending, true) } this._enqueueRpc(pending, true) @@ -1586,11 +1321,7 @@ export class SessionConnection extends PersistentConnection { } private _flush(): void { - if ( - !this._session._authKey.ready || - this._isPfsBindingPending || - this._session.current429Timeout - ) { + if (!this._session._authKey.ready || this._isPfsBindingPending || this._session.current429Timeout) { this.log.debug( 'skipping flush, connection is not usable (auth key ready = %b, pfs binding pending = %b, 429 timeout = %b)', this._session._authKey.ready, @@ -1628,10 +1359,7 @@ export class SessionConnection extends PersistentConnection { } private _doFlush(): void { - this.log.debug( - 'flushing send queue. queued rpc: %d', - this._session.queuedRpc.length, - ) + this.log.debug('flushing send queue. queued rpc: %d', this._session.queuedRpc.length) // oh bloody hell mate @@ -1688,13 +1416,8 @@ export class SessionConnection extends PersistentConnection { if (now - this._session.lastPingTime > 60000) { if (!this._session.lastPingMsgId.isZero()) { - this.log.warn( - "didn't receive pong for previous ping (msg_id = %l)", - this._session.lastPingMsgId, - ) - this._session.pendingMessages.delete( - this._session.lastPingMsgId, - ) + this.log.warn("didn't receive pong for previous ping (msg_id = %l)", this._session.lastPingMsgId) + this._session.pendingMessages.delete(this._session.lastPingMsgId) } pingId = randomLong() @@ -1723,16 +1446,10 @@ export class SessionConnection extends PersistentConnection { getStateMsgIds = ids } - const idx = this._session.getStateSchedule.index( - { getState: now } as PendingRpc, - true, - ) + const idx = this._session.getStateSchedule.index({ getState: now } as PendingRpc, true) if (idx > 0) { - const toGetState = this._session.getStateSchedule.raw.splice( - 0, - idx, - ) + const toGetState = this._session.getStateSchedule.raw.splice(0, idx) if (!getStateMsgIds) getStateMsgIds = [] toGetState.forEach((it) => getStateMsgIds!.push(it.msgId!)) } @@ -1743,10 +1460,7 @@ export class SessionConnection extends PersistentConnection { msgIds: getStateMsgIds, } - getStateRequest = TlBinaryWriter.serializeObject( - this._writerMap, - obj, - ) + getStateRequest = TlBinaryWriter.serializeObject(this._writerMap, obj) packetSize += getStateRequest.length + 16 messageCount += 1 } @@ -1836,21 +1550,14 @@ export class SessionConnection extends PersistentConnection { writer.uint(messageCount) } - const otherPendings: Exclude< - PendingMessage, - { _: 'rpc' | 'container' | 'bind' } - >[] = [] + const otherPendings: Exclude[] = [] if (ackRequest) { - this._registerOutgoingMsgId( - this._session.writeMessage(writer, ackRequest), - ) + this._registerOutgoingMsgId(this._session.writeMessage(writer, ackRequest)) } if (pingRequest) { - pingMsgId = this._registerOutgoingMsgId( - this._session.writeMessage(writer, pingRequest), - ) + pingMsgId = this._registerOutgoingMsgId(this._session.writeMessage(writer, pingRequest)) this._session.lastPingMsgId = pingMsgId const pingPending: PendingMessage = { _: 'ping', @@ -1862,9 +1569,7 @@ export class SessionConnection extends PersistentConnection { } if (getStateRequest) { - getStateMsgId = this._registerOutgoingMsgId( - this._session.writeMessage(writer, getStateRequest), - ) + getStateMsgId = this._registerOutgoingMsgId(this._session.writeMessage(writer, getStateRequest)) const getStatePending: PendingMessage = { _: 'state', msgIds: getStateMsgIds!, @@ -1875,9 +1580,7 @@ export class SessionConnection extends PersistentConnection { } if (resendRequest) { - resendMsgId = this._registerOutgoingMsgId( - this._session.writeMessage(writer, resendRequest), - ) + resendMsgId = this._registerOutgoingMsgId(this._session.writeMessage(writer, resendRequest)) const resendPending: PendingMessage = { _: 'resend', msgIds: resendMsgIds!, @@ -1936,12 +1639,7 @@ export class SessionConnection extends PersistentConnection { const msgId = this._session.getMessageId() const seqNo = this._session.getSeqNo() - this.log.debug( - '%s: msg_id assigned %l, seqno: %d', - msg.method, - msgId, - seqNo, - ) + this.log.debug('%s: msg_id assigned %l, seqno: %d', msg.method, msgId, seqNo) msg.msgId = msgId msg.seqNo = seqNo @@ -1950,12 +1648,7 @@ export class SessionConnection extends PersistentConnection { rpc: msg, }) } else { - this.log.debug( - '%s: msg_id already assigned, reusing %l, seqno: %d', - msg.method, - msg.msgId, - msg.seqNo, - ) + this.log.debug('%s: msg_id already assigned, reusing %l, seqno: %d', msg.method, msg.msgId, msg.seqNo) } // (re-)schedule get_state if needed @@ -2042,11 +1735,7 @@ export class SessionConnection extends PersistentConnection { .encryptMessage(result) .then((enc) => this.send(enc)) .catch((err: Error) => { - this.log.error( - 'error while sending pending messages (root msg_id = %l): %s', - rootMsgId, - err.stack, - ) + this.log.error('error while sending pending messages (root msg_id = %l): %s', rootMsgId, err.stack) // put acks in the front so they are the first to be sent if (ackMsgIds) { diff --git a/packages/core/src/network/transports/index.ts b/packages/core/src/network/transports/index.ts index ccb4e1d0..eeb620f5 100644 --- a/packages/core/src/network/transports/index.ts +++ b/packages/core/src/network/transports/index.ts @@ -11,5 +11,4 @@ export * from './wrapped' import { _defaultTransportFactory } from '../../utils/platform/transport' /** Platform-defined default transport factory */ -export const defaultTransportFactory: TransportFactory = - _defaultTransportFactory +export const defaultTransportFactory: TransportFactory = _defaultTransportFactory diff --git a/packages/core/src/network/transports/intermediate.ts b/packages/core/src/network/transports/intermediate.ts index 39f97192..91de3b50 100644 --- a/packages/core/src/network/transports/intermediate.ts +++ b/packages/core/src/network/transports/intermediate.ts @@ -9,9 +9,7 @@ const PADDED_TAG = Buffer.from([0xdd, 0xdd, 0xdd, 0xdd]) * Intermediate packet codec. * See https://core.telegram.org/mtproto/mtproto-transports#intermediate */ -export class IntermediatePacketCodec - extends StreamedCodec - implements IPacketCodec { +export class IntermediatePacketCodec extends StreamedCodec implements IPacketCodec { tag(): Buffer { return TAG } diff --git a/packages/core/src/network/transports/obfuscated.ts b/packages/core/src/network/transports/obfuscated.ts index c7934f18..7187b855 100644 --- a/packages/core/src/network/transports/obfuscated.ts +++ b/packages/core/src/network/transports/obfuscated.ts @@ -18,9 +18,7 @@ export interface MtProxyInfo { media: boolean } -export class ObfuscatedPacketCodec - extends WrappedCodec - implements IPacketCodec { +export class ObfuscatedPacketCodec extends WrappedCodec implements IPacketCodec { private _encryptor?: IEncryptionScheme private _decryptor?: IEncryptionScheme @@ -71,20 +69,12 @@ export class ObfuscatedPacketCodec const decryptIv = randomRev.slice(32, 48) if (this._proxy) { - encryptKey = await this._crypto.sha256( - Buffer.concat([encryptKey, this._proxy.secret]), - ) - decryptKey = await this._crypto.sha256( - Buffer.concat([decryptKey, this._proxy.secret]), - ) + encryptKey = await this._crypto.sha256(Buffer.concat([encryptKey, this._proxy.secret])) + decryptKey = await this._crypto.sha256(Buffer.concat([decryptKey, this._proxy.secret])) } this._encryptor = this._crypto.createAesCtr(encryptKey, encryptIv, true) - this._decryptor = this._crypto.createAesCtr( - decryptKey, - decryptIv, - false, - ) + this._decryptor = this._crypto.createAesCtr(decryptKey, decryptIv, false) const encrypted = await this._encryptor.encrypt(random) encrypted.copy(random, 56, 56, 64) @@ -101,9 +91,7 @@ export class ObfuscatedPacketCodec if (Buffer.isBuffer(dec)) this._inner.feed(dec) else { - dec.then((dec) => this._inner.feed(dec)).catch((err) => - this.emit('error', err), - ) + dec.then((dec) => this._inner.feed(dec)).catch((err) => this.emit('error', err)) } } diff --git a/packages/core/src/network/transports/tcp.ts b/packages/core/src/network/transports/tcp.ts index df8a7c09..86c76e76 100644 --- a/packages/core/src/network/transports/tcp.ts +++ b/packages/core/src/network/transports/tcp.ts @@ -12,9 +12,7 @@ import { IntermediatePacketCodec } from './intermediate' * Base for TCP transports. * Subclasses must provide packet codec in `_packetCodec` property */ -export abstract class BaseTcpTransport - extends EventEmitter - implements ITelegramTransport { +export abstract class BaseTcpTransport extends EventEmitter implements ITelegramTransport { protected _currentDc: tl.RawDcOption | null = null protected _state: TransportState = TransportState.Idle protected _socket: Socket | null = null @@ -66,11 +64,7 @@ export abstract class BaseTcpTransport this.log.debug('connecting to %j', dc) - this._socket = connect( - dc.port, - dc.ipAddress, - this.handleConnect.bind(this), - ) + this._socket = connect(dc.port, dc.ipAddress, this.handleConnect.bind(this)) this._socket.on('data', (data) => { this._packetCodec.feed(data) @@ -105,10 +99,7 @@ export abstract class BaseTcpTransport if (initialMessage.length) { this._socket!.write(initialMessage, (err) => { if (err) { - this.log.error( - 'failed to write initial message: %s', - err.stack, - ) + this.log.error('failed to write initial message: %s', err.stack) this.emit('error') this.close() } else { diff --git a/packages/core/src/network/transports/websocket.ts b/packages/core/src/network/transports/websocket.ts index 98a6592c..ba3f902e 100644 --- a/packages/core/src/network/transports/websocket.ts +++ b/packages/core/src/network/transports/websocket.ts @@ -35,9 +35,7 @@ const subdomainsMap: Record = { * Base for WebSocket transports. * Subclasses must provide packet codec in `_packetCodec` property */ -export abstract class BaseWebSocketTransport - extends EventEmitter - implements ITelegramTransport { +export abstract class BaseWebSocketTransport extends EventEmitter implements ITelegramTransport { private _currentDc: tl.RawDcOption | null = null private _state: TransportState = TransportState.Idle private _socket: WebSocket | null = null @@ -58,9 +56,7 @@ export abstract class BaseWebSocketTransport super() if (!ws) { - throw new MtUnsupportedError( - 'To use WebSocket transport with NodeJS, install `ws` package.', - ) + throw new MtUnsupportedError('To use WebSocket transport with NodeJS, install `ws` package.') } this._baseDomain = baseDomain @@ -71,9 +67,7 @@ export abstract class BaseWebSocketTransport private _updateLogPrefix() { if (this._currentDc) { - this.log.prefix = `[WS:${this._subdomains[this._currentDc.id]}.${ - this._baseDomain - }] ` + this.log.prefix = `[WS:${this._subdomains[this._currentDc.id]}.${this._baseDomain}] ` } else { this.log.prefix = '[WS:disconnected] ' } @@ -107,9 +101,7 @@ export abstract class BaseWebSocketTransport this._state = TransportState.Connecting this._currentDc = dc this._socket = new ws!( - `wss://${this._subdomains[dc.id]}.${this._baseDomain}/apiws${ - testMode ? '_test' : '' - }`, + `wss://${this._subdomains[dc.id]}.${this._baseDomain}/apiws${testMode ? '_test' : ''}`, 'binary', ) @@ -119,9 +111,7 @@ export abstract class BaseWebSocketTransport this._socket.binaryType = 'arraybuffer' this._socket.addEventListener('message', (evt) => - this._packetCodec.feed( - typedArrayToBuffer(evt.data as NodeJS.TypedArray), - ), + this._packetCodec.feed(typedArrayToBuffer(evt.data as NodeJS.TypedArray)), ) this._socket.addEventListener('open', this.handleConnect.bind(this)) this._socket.addEventListener('error', this.handleError.bind(this)) @@ -142,10 +132,7 @@ export abstract class BaseWebSocketTransport } handleError(event: Event | { error: Error }): void { - const error = - 'error' in event ? - event.error : - new Error('unknown WebSocket error') + const error = 'error' in event ? event.error : new Error('unknown WebSocket error') this.log.error('error: %s', error.stack) this.emit('error', error) diff --git a/packages/core/src/storage/abstract.ts b/packages/core/src/storage/abstract.ts index a1de7c18..3b9bcdb6 100644 --- a/packages/core/src/storage/abstract.ts +++ b/packages/core/src/storage/abstract.ts @@ -97,12 +97,7 @@ export interface ITelegramStorage { * Set temp_auth_key for a given DC * expiresAt is unix time in ms */ - setTempAuthKeyFor( - dcId: number, - index: number, - key: Buffer | null, - expiresAt: number - ): MaybeAsync + setTempAuthKeyFor(dcId: number, index: number, key: Buffer | null, expiresAt: number): MaybeAsync /** * Remove all saved auth keys (both temp and perm) * for the given DC. Used when perm_key becomes invalid, diff --git a/packages/core/src/storage/json-file.ts b/packages/core/src/storage/json-file.ts index 9acd4813..4d9cb91f 100644 --- a/packages/core/src/storage/json-file.ts +++ b/packages/core/src/storage/json-file.ts @@ -61,15 +61,11 @@ export class JsonFileStorage extends JsonMemoryStorage { this._cleanup = params?.cleanup ?? Boolean(exitHook) if (this._cleanup && !exitHook) { - throw new MtUnsupportedError( - 'Cleanup on exit is supported through `exit-hook` library, install it first!', - ) + throw new MtUnsupportedError('Cleanup on exit is supported through `exit-hook` library, install it first!') } if (this._cleanup) { - this._unsubscribe = exitHook!.default( - this._onProcessExit.bind(this), - ) + this._unsubscribe = exitHook!.default(this._onProcessExit.bind(this)) } } @@ -77,9 +73,7 @@ export class JsonFileStorage extends JsonMemoryStorage { try { this._loadJson( await new Promise((res, rej) => - fs!.readFile(this._filename, 'utf-8', (err, data) => - err ? rej(err) : res(data), - ), + fs!.readFile(this._filename, 'utf-8', (err, data) => (err ? rej(err) : res(data))), ), ) } catch (e) {} @@ -87,23 +81,15 @@ export class JsonFileStorage extends JsonMemoryStorage { save(): Promise { return new Promise((resolve, reject) => { - fs!.writeFile( - this._safe ? this._filename + '.tmp' : this._filename, - this._saveJson(), - (err) => { - if (err) reject(err) - else if (this._safe) { - fs!.rename( - this._filename + '.tmp', - this._filename, - (err) => { - if (err && err.code !== 'ENOENT') reject(err) - else resolve() - }, - ) - } else resolve() - }, - ) + fs!.writeFile(this._safe ? this._filename + '.tmp' : this._filename, this._saveJson(), (err) => { + if (err) reject(err) + else if (this._safe) { + fs!.rename(this._filename + '.tmp', this._filename, (err) => { + if (err && err.code !== 'ENOENT') reject(err) + else resolve() + }) + } else resolve() + }) }) } diff --git a/packages/core/src/storage/json.ts b/packages/core/src/storage/json.ts index ade7f90c..e6d45ab8 100644 --- a/packages/core/src/storage/json.ts +++ b/packages/core/src/storage/json.ts @@ -17,12 +17,10 @@ export class JsonMemoryStorage extends MemoryStorage { case 'authKeysTemp': { const ret: Record = {} - ;(value as string) - .split('|') - .forEach((pair: string) => { - const [dcId, b64] = pair.split(',') - ret[dcId] = Buffer.from(b64, 'base64') - }) + ;(value as string).split('|').forEach((pair: string) => { + const [dcId, b64] = pair.split(',') + ret[dcId] = Buffer.from(b64, 'base64') + }) return ret } @@ -33,9 +31,7 @@ export class JsonMemoryStorage extends MemoryStorage { case 'pts': case 'fsm': case 'rl': - return new Map( - Object.entries(value as Record), - ) + return new Map(Object.entries(value as Record)) case 'accessHash': return longFromFastString(value as string) } @@ -54,9 +50,7 @@ export class JsonMemoryStorage extends MemoryStorage { return [...value_.entries()] .filter((it): it is [string, Buffer] => it[1] !== null) - .map( - ([dcId, key]) => dcId + ',' + key.toString('base64'), - ) + .map(([dcId, key]) => dcId + ',' + key.toString('base64')) .join('|') } case 'authKeysTempExpiry': @@ -66,9 +60,7 @@ export class JsonMemoryStorage extends MemoryStorage { case 'pts': case 'fsm': case 'rl': - return Object.fromEntries([ - ...(value as Map).entries(), - ]) + return Object.fromEntries([...(value as Map).entries()]) case 'accessHash': return longToFastString(value as tl.Long) } diff --git a/packages/core/src/storage/memory.ts b/packages/core/src/storage/memory.ts index 4419388b..32943afc 100644 --- a/packages/core/src/storage/memory.ts +++ b/packages/core/src/storage/memory.ts @@ -59,9 +59,7 @@ const USERNAME_TTL = 86400000 // 24 hours export class MemoryStorage implements ITelegramStorage, IStateStorage { protected _state!: MemorySessionState - private _cachedInputPeers: LruMap = new LruMap( - 100, - ) + private _cachedInputPeers: LruMap = new LruMap(100) private _cachedFull: LruMap @@ -97,10 +95,7 @@ export class MemoryStorage implements ITelegramStorage, IStateStorage { } load(): void { - this._vacuumTimeout = setInterval( - this._vacuum.bind(this), - this._vacuumInterval, - ) + this._vacuumTimeout = setInterval(this._vacuum.bind(this), this._vacuumInterval) } destroy(): void { @@ -147,15 +142,13 @@ export class MemoryStorage implements ITelegramStorage, IStateStorage { } if (populate) { - Object.values(obj.entities).forEach( - (ent: ITelegramStorage.PeerInfo) => { - if (ent.phone) obj.phoneIndex.set(ent.phone, ent.id) + Object.values(obj.entities).forEach((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) + } + }) } this._state = obj @@ -192,12 +185,7 @@ export class MemoryStorage implements ITelegramStorage, IStateStorage { this._state.defaultDcs = dcs } - setTempAuthKeyFor( - dcId: number, - index: number, - key: Buffer | null, - expiresAt: number, - ): void { + setTempAuthKeyFor(dcId: number, index: number, key: Buffer | null, expiresAt: number): void { const k = `${dcId}:${index}` if (key) { @@ -269,9 +257,7 @@ export class MemoryStorage implements ITelegramStorage, IStateStorage { } } - protected _getInputPeer( - peerInfo?: ITelegramStorage.PeerInfo, - ): tl.TypeInputPeer | null { + protected _getInputPeer(peerInfo?: ITelegramStorage.PeerInfo): tl.TypeInputPeer | null { if (!peerInfo) return null switch (peerInfo.type) { diff --git a/packages/core/src/types/errors.ts b/packages/core/src/types/errors.ts index 04f26a50..69d0c5a7 100644 --- a/packages/core/src/types/errors.ts +++ b/packages/core/src/types/errors.ts @@ -49,9 +49,7 @@ export class MtTypeAssertionError extends MtcuteError { actual: string constructor(context: string, expected: string, actual: string) { - super( - `Type assertion error at ${context}: expected ${expected}, but got ${actual}`, - ) + super(`Type assertion error at ${context}: expected ${expected}, but got ${actual}`) this.context = context this.expected = expected this.actual = actual diff --git a/packages/core/src/types/utils.ts b/packages/core/src/types/utils.ts index e32a5b89..083d8e8c 100644 --- a/packages/core/src/types/utils.ts +++ b/packages/core/src/types/utils.ts @@ -1,6 +1,5 @@ export type MaybeAsync = T | Promise -export type PartialExcept = Partial> & - Pick +export type PartialExcept = Partial> & Pick export type PartialOnly = Partial> & Omit export type MaybeArray = T | T[] diff --git a/packages/core/src/utils/bigint-utils.ts b/packages/core/src/utils/bigint-utils.ts index d5a7f65d..5b821e8b 100644 --- a/packages/core/src/utils/bigint-utils.ts +++ b/packages/core/src/utils/bigint-utils.ts @@ -9,11 +9,7 @@ import { randomBytes } from './buffer-utils' * @param length Length of the resulting buffer (by default it's computed automatically) * @param le Whether to use little-endian encoding */ -export function bigIntToBuffer( - value: BigInteger, - length = 0, - le = false, -): Buffer { +export function bigIntToBuffer(value: BigInteger, length = 0, le = false): Buffer { const array = value.toArray(256).value if (length !== 0 && array.length > length) { @@ -41,12 +37,7 @@ export function bigIntToBuffer( * @param length Length to read * @param le Whether to use little-endian encoding */ -export function bufferToBigInt( - buffer: Buffer, - offset = 0, - length = buffer.length, - le = false, -): BigInteger { +export function bufferToBigInt(buffer: Buffer, offset = 0, length = buffer.length, le = false): BigInteger { const arr = [...buffer.slice(offset, offset + length)] if (le) arr.reverse() @@ -85,10 +76,7 @@ export function randomBigIntBits(bits: number): BigInteger { * @param max Maximum value (exclusive) * @param min Minimum value (inclusive) */ -export function randomBigIntInRange( - max: BigInteger, - min = bigInt.one, -): BigInteger { +export function randomBigIntInRange(max: BigInteger, min = bigInt.one): BigInteger { const interval = max.minus(min) if (interval.isNegative()) throw new Error('expected min < max') diff --git a/packages/core/src/utils/binary/asn1-parser.ts b/packages/core/src/utils/binary/asn1-parser.ts index d7a3a6c2..8da558c2 100644 --- a/packages/core/src/utils/binary/asn1-parser.ts +++ b/packages/core/src/utils/binary/asn1-parser.ts @@ -5,10 +5,7 @@ * In fact just strips begin/end tags and parses the rest as Base64 */ export function parsePemContents(pem: string): Buffer { - return Buffer.from( - pem.replace(/^-----(BEGIN|END)( RSA)? PUBLIC KEY-----$|\n/gm, ''), - 'base64', - ) + return Buffer.from(pem.replace(/^-----(BEGIN|END)( RSA)? PUBLIC KEY-----$|\n/gm, ''), 'base64') } // based on https://git.coolaj86.com/coolaj86/asn1-parser.js/src/branch/master/asn1-parser.js @@ -85,17 +82,10 @@ export function parseAsn1(data: Buffer): Asn1Object { function parseChildren(eager = false) { asn1.children = [] - while ( - iters < ELOOPN && - index < 2 + asn1.length + asn1.lengthSize - ) { + while (iters < ELOOPN && index < 2 + asn1.length + asn1.lengthSize) { iters += 1 depth.length += 1 - child = parseAsn1Inner( - buf.slice(index, index + adjustedLen), - depth, - eager, - ) + child = parseAsn1Inner(buf.slice(index, index + adjustedLen), depth, eager) depth.length -= 1 // The numbers don't match up exactly and I don't remember why... // probably something with adjustedLen or some such, but the tests pass @@ -104,9 +94,7 @@ export function parseAsn1(data: Buffer): Asn1Object { if (index > 2 + asn1.lengthSize + asn1.length) { throw new Error( `Parse error: child value length (${child.length}) is ` + - `greater than remaining parent length (${ - asn1.length - index - } = ${asn1.length} - ${index})`, + `greater than remaining parent length (${asn1.length - index} = ${asn1.length} - ${index})`, ) } asn1.children.push(child) @@ -150,9 +138,7 @@ export function parseAsn1(data: Buffer): Asn1Object { const len = data.length if (len !== 2 + asn1.lengthSize + asn1.length) { - throw new Error( - 'Length of buffer does not match length of ASN.1 sequence.', - ) + throw new Error('Length of buffer does not match length of ASN.1 sequence.') } return asn1 diff --git a/packages/core/src/utils/buffer-utils.ts b/packages/core/src/utils/buffer-utils.ts index dc8e060d..1e5b3245 100644 --- a/packages/core/src/utils/buffer-utils.ts +++ b/packages/core/src/utils/buffer-utils.ts @@ -9,11 +9,9 @@ const b64urlAvailable = Buffer.isEncoding('base64url') * @param arr Typed array to convert */ export function typedArrayToBuffer(arr: NodeJS.TypedArray): Buffer { - return ArrayBuffer.isView(arr) ? - // To avoid a copy, use the typed array's underlying ArrayBuffer to back + return ArrayBuffer.isView(arr) ? // To avoid a copy, use the typed array's underlying ArrayBuffer to back // new Buffer, respecting the "view", i.e. byteOffset and byteLength - Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength) : - // Pass through all other types to `Buffer.from` + Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength) : // Pass through all other types to `Buffer.from` Buffer.from(arr) } @@ -101,9 +99,5 @@ export function encodeUrlSafeBase64(buf: Buffer): string { return buf.toString('base64url') } - return buf - .toString('base64') - .replace(/\+/g, '-') - .replace(/\//g, '_') - .replace(/=+$/g, '') + return buf.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '') } diff --git a/packages/core/src/utils/controllable-promise.ts b/packages/core/src/utils/controllable-promise.ts index 1f22e38b..f4ee68b9 100644 --- a/packages/core/src/utils/controllable-promise.ts +++ b/packages/core/src/utils/controllable-promise.ts @@ -31,7 +31,6 @@ export function createControllablePromise(): ControllablePromise // ts doesn't like this, but it's fine ;(promise as ControllablePromise).resolve = _resolve! - ;(promise as ControllablePromise).reject = _reject! return promise as ControllablePromise diff --git a/packages/core/src/utils/crypto/abstract.ts b/packages/core/src/utils/crypto/abstract.ts index 78d1e022..419d666e 100644 --- a/packages/core/src/utils/crypto/abstract.ts +++ b/packages/core/src/utils/crypto/abstract.ts @@ -20,7 +20,7 @@ export interface ICryptoProvider { salt: Buffer, iterations: number, keylen?: number, // = 64 - algo?: string // sha1 or sha512 (default sha512) + algo?: string, // sha1 or sha512 (default sha512) ): MaybeAsync hmacSha256(data: Buffer, key: Buffer): MaybeAsync diff --git a/packages/core/src/utils/crypto/common.ts b/packages/core/src/utils/crypto/common.ts index e86f1e07..d379395a 100644 --- a/packages/core/src/utils/crypto/common.ts +++ b/packages/core/src/utils/crypto/common.ts @@ -17,9 +17,7 @@ export class AesModeOfOperationIge implements IEncryptionScheme { async encrypt(data: Buffer): Promise { if (data.length % 16 !== 0) { - throw new Error( - 'invalid plaintext size (must be multiple of 16 bytes)', - ) + throw new Error('invalid plaintext size (must be multiple of 16 bytes)') } const ciphertext = Buffer.alloc(data.length) @@ -44,9 +42,7 @@ export class AesModeOfOperationIge implements IEncryptionScheme { async decrypt(data: Buffer): Promise { if (data.length % 16 !== 0) { - throw new Error( - 'invalid ciphertext size (must be multiple of 16 bytes)', - ) + throw new Error('invalid ciphertext size (must be multiple of 16 bytes)') } const plaintext = Buffer.alloc(data.length) diff --git a/packages/core/src/utils/crypto/factorization.ts b/packages/core/src/utils/crypto/factorization.ts index 93e5ba05..c27c7276 100644 --- a/packages/core/src/utils/crypto/factorization.ts +++ b/packages/core/src/utils/crypto/factorization.ts @@ -1,10 +1,6 @@ import bigInt, { BigInteger } from 'big-integer' -import { - bigIntToBuffer, - bufferToBigInt, - randomBigIntInRange, -} from '../bigint-utils' +import { bigIntToBuffer, bufferToBigInt, randomBigIntInRange } from '../bigint-utils' /** * Factorize `p*q` to `p` and `q` synchronously using Brent-Pollard rho algorithm @@ -16,7 +12,8 @@ export function factorizePQSync(pq: Buffer): [Buffer, Buffer] { const n = PollardRhoBrent(pq_) const m = pq_.divide(n) - let p; let q + let p + let q if (n.lt(m)) { p = n @@ -52,11 +49,7 @@ function PollardRhoBrent(n: BigInteger): BigInteger { while (k.lt(r) && g.eq(1)) { ys = y - for ( - let i = bigInt.zero; - i.lt(bigInt.min(m, r.minus(k))); - i = i.plus(bigInt.one) - ) { + for (let i = bigInt.zero; i.lt(bigInt.min(m, r.minus(k))); i = i.plus(bigInt.one)) { y = y.multiply(y).mod(n).plus(c).mod(n) q = q.multiply(x.minus(y).abs()).mod(n) // y = (y * y % n + c) % n diff --git a/packages/core/src/utils/crypto/forge-crypto.ts b/packages/core/src/utils/crypto/forge-crypto.ts index c4c6cb4e..7778e792 100644 --- a/packages/core/src/utils/crypto/forge-crypto.ts +++ b/packages/core/src/utils/crypto/forge-crypto.ts @@ -1,11 +1,7 @@ import type * as forgeNs from 'node-forge' import { MaybeAsync } from '../../types' -import { - BaseCryptoProvider, - ICryptoProvider, - IEncryptionScheme, -} from './abstract' +import { BaseCryptoProvider, ICryptoProvider, IEncryptionScheme } from './abstract' type forge = typeof forgeNs let forge: forge | null = null @@ -14,23 +10,17 @@ try { forge = require('node-forge') as forge } catch (e) {} -export class ForgeCryptoProvider - extends BaseCryptoProvider - implements ICryptoProvider { +export class ForgeCryptoProvider extends BaseCryptoProvider implements ICryptoProvider { constructor() { super() if (!forge) { - throw new Error( - 'For ForgeCryptoProvider you must have node-forge installed!', - ) + throw new Error('For ForgeCryptoProvider you must have node-forge installed!') } } createAesCtr(key: Buffer, iv: Buffer, encrypt: boolean): IEncryptionScheme { - const cipher = forge!.cipher[ - encrypt ? 'createCipher' : 'createDecipher' - ]('AES-CTR', key.toString('binary')) + const cipher = forge!.cipher[encrypt ? 'createCipher' : 'createDecipher']('AES-CTR', key.toString('binary')) cipher.start({ iv: iv.toString('binary') }) const update = (data: Buffer): Buffer => { @@ -61,10 +51,7 @@ export class ForgeCryptoProvider return Buffer.from(cipher.output.data, 'binary') }, decrypt(data: Buffer) { - const cipher = forge!.cipher.createDecipher( - 'AES-ECB', - keyBuffer, - ) + const cipher = forge!.cipher.createDecipher('AES-ECB', keyBuffer) cipher.start({}) // @ts-expect-error wrong types cipher.mode.pad = cipher.mode.unpad = false @@ -76,13 +63,7 @@ export class ForgeCryptoProvider } } - pbkdf2( - password: Buffer, - salt: Buffer, - iterations: number, - keylen = 64, - algo = 'sha512', - ): MaybeAsync { + pbkdf2(password: Buffer, salt: Buffer, iterations: number, keylen = 64, algo = 'sha512'): MaybeAsync { return new Promise((resolve, reject) => forge!.pkcs5.pbkdf2( password.toString('binary'), @@ -91,28 +72,17 @@ export class ForgeCryptoProvider keylen, // eslint-disable-next-line (forge!.md as any)[algo].create(), - (err: Error | null, buf: string) => - err !== null ? - reject(err) : - resolve(Buffer.from(buf, 'binary')), + (err: Error | null, buf: string) => (err !== null ? reject(err) : resolve(Buffer.from(buf, 'binary'))), ), ) } sha1(data: Buffer): MaybeAsync { - return Buffer.from( - forge!.md.sha1.create().update(data.toString('binary')).digest() - .data, - 'binary', - ) + return Buffer.from(forge!.md.sha1.create().update(data.toString('binary')).digest().data, 'binary') } sha256(data: Buffer): MaybeAsync { - return Buffer.from( - forge!.md.sha256.create().update(data.toString('binary')).digest() - .data, - 'binary', - ) + return Buffer.from(forge!.md.sha256.create().update(data.toString('binary')).digest().data, 'binary') } hmacSha256(data: Buffer, key: Buffer): MaybeAsync { diff --git a/packages/core/src/utils/crypto/index.ts b/packages/core/src/utils/crypto/index.ts index 4e8ed81e..db4124f5 100644 --- a/packages/core/src/utils/crypto/index.ts +++ b/packages/core/src/utils/crypto/index.ts @@ -10,5 +10,4 @@ export { ForgeCryptoProvider, NodeCryptoProvider } import { _defaultCryptoProviderFactory } from '../platform/crypto' import { CryptoProviderFactory } from './abstract' -export const defaultCryptoProviderFactory: CryptoProviderFactory = - _defaultCryptoProviderFactory +export const defaultCryptoProviderFactory: CryptoProviderFactory = _defaultCryptoProviderFactory diff --git a/packages/core/src/utils/crypto/keys.ts b/packages/core/src/utils/crypto/keys.ts index d6a92f0d..99ee11a6 100644 --- a/packages/core/src/utils/crypto/keys.ts +++ b/packages/core/src/utils/crypto/keys.ts @@ -14,11 +14,7 @@ import { ICryptoProvider } from './abstract' * @param key PEM-encoded RSA public key * @param old Whether this is an "old" key */ -export async function parsePublicKey( - crypto: ICryptoProvider, - key: string, - old = false, -): Promise { +export async function parsePublicKey(crypto: ICryptoProvider, key: string, old = false): Promise { const asn1 = parseAsn1(parsePemContents(key)) const modulus = asn1.children?.[0].value const exponent = asn1.children?.[1].value @@ -48,11 +44,7 @@ export async function parsePublicKey( * @param key PEM-encoded RSA public key * @param old Whether this is an "old" key */ -export async function addPublicKey( - crypto: ICryptoProvider, - key: string, - old = false, -): Promise { +export async function addPublicKey(crypto: ICryptoProvider, key: string, old = false): Promise { const parsed = await parsePublicKey(crypto, key, old) keysIndex[parsed.fingerprint] = parsed } @@ -63,10 +55,7 @@ export async function addPublicKey( * @param fingerprints Fingerprints to match. The first one to match is returned. * @param allowOld Whether to allow "old" keys */ -export function findKeyByFingerprints( - fingerprints: (string | Long)[], - allowOld = false, -): TlPublicKey | null { +export function findKeyByFingerprints(fingerprints: (string | Long)[], allowOld = false): TlPublicKey | null { for (let fp of fingerprints) { if (typeof fp !== 'string') { fp = fp.toUnsigned().toString(16) diff --git a/packages/core/src/utils/crypto/mtproto.ts b/packages/core/src/utils/crypto/mtproto.ts index cf2b6eb6..52cc3711 100644 --- a/packages/core/src/utils/crypto/mtproto.ts +++ b/packages/core/src/utils/crypto/mtproto.ts @@ -40,23 +40,11 @@ export async function createAesIgeForMessage( client: boolean, ): Promise { const x = client ? 0 : 8 - const sha256a = await crypto.sha256( - Buffer.concat([messageKey, authKey.slice(x, 36 + x)]), - ) - const sha256b = await crypto.sha256( - Buffer.concat([authKey.slice(40 + x, 76 + x), messageKey]), - ) + const sha256a = await crypto.sha256(Buffer.concat([messageKey, authKey.slice(x, 36 + x)])) + const sha256b = await crypto.sha256(Buffer.concat([authKey.slice(40 + x, 76 + x), messageKey])) - const key = Buffer.concat([ - sha256a.slice(0, 8), - sha256b.slice(8, 24), - sha256a.slice(24, 32), - ]) - const iv = Buffer.concat([ - sha256b.slice(0, 8), - sha256a.slice(8, 24), - sha256b.slice(24, 32), - ]) + const key = Buffer.concat([sha256a.slice(0, 8), sha256b.slice(8, 24), sha256a.slice(24, 32)]) + const iv = Buffer.concat([sha256b.slice(0, 8), sha256a.slice(8, 24), sha256b.slice(24, 32)]) return crypto.createAesIge(key, iv) } @@ -77,34 +65,15 @@ export async function createAesIgeForMessageOld( client: boolean, ): Promise { const x = client ? 0 : 8 - const sha1a = await crypto.sha1( - Buffer.concat([messageKey, authKey.slice(x, 32 + x)]), - ) + const sha1a = await crypto.sha1(Buffer.concat([messageKey, authKey.slice(x, 32 + x)])) const sha1b = await crypto.sha1( - Buffer.concat([ - authKey.slice(32 + x, 48 + x), - messageKey, - authKey.slice(48 + x, 64 + x), - ]), - ) - const sha1c = await crypto.sha1( - Buffer.concat([authKey.slice(64 + x, 96 + x), messageKey]), - ) - const sha1d = await crypto.sha1( - Buffer.concat([messageKey, authKey.slice(96 + x, 128 + x)]), + Buffer.concat([authKey.slice(32 + x, 48 + x), messageKey, authKey.slice(48 + x, 64 + x)]), ) + const sha1c = await crypto.sha1(Buffer.concat([authKey.slice(64 + x, 96 + x), messageKey])) + const sha1d = await crypto.sha1(Buffer.concat([messageKey, authKey.slice(96 + x, 128 + x)])) - const key = Buffer.concat([ - sha1a.slice(0, 8), - sha1b.slice(8, 20), - sha1c.slice(4, 16), - ]) - const iv = Buffer.concat([ - sha1a.slice(8, 20), - sha1b.slice(0, 8), - sha1c.slice(16, 20), - sha1d.slice(0, 8), - ]) + const key = Buffer.concat([sha1a.slice(0, 8), sha1b.slice(8, 20), sha1c.slice(4, 16)]) + const iv = Buffer.concat([sha1a.slice(8, 20), sha1b.slice(0, 8), sha1c.slice(16, 20), sha1d.slice(0, 8)]) return crypto.createAesIge(key, iv) } diff --git a/packages/core/src/utils/crypto/node-crypto.ts b/packages/core/src/utils/crypto/node-crypto.ts index e913c67e..3eac6b61 100644 --- a/packages/core/src/utils/crypto/node-crypto.ts +++ b/packages/core/src/utils/crypto/node-crypto.ts @@ -1,27 +1,11 @@ -import { - createCipheriv, - createDecipheriv, - createHash, - createHmac, - pbkdf2, -} from 'crypto' +import { createCipheriv, createDecipheriv, createHash, createHmac, pbkdf2 } from 'crypto' import { MaybeAsync } from '../../types' -import { - BaseCryptoProvider, - ICryptoProvider, - IEncryptionScheme, -} from './abstract' +import { BaseCryptoProvider, ICryptoProvider, IEncryptionScheme } from './abstract' -export class NodeCryptoProvider - extends BaseCryptoProvider - implements ICryptoProvider { +export class NodeCryptoProvider extends BaseCryptoProvider implements ICryptoProvider { createAesCtr(key: Buffer, iv: Buffer, encrypt: boolean): IEncryptionScheme { - const cipher = (encrypt ? createCipheriv : createDecipheriv)( - `aes-${key.length * 8}-ctr`, - key, - iv, - ) + const cipher = (encrypt ? createCipheriv : createDecipheriv)(`aes-${key.length * 8}-ctr`, key, iv) const update = (data: Buffer) => cipher.update(data) @@ -50,22 +34,10 @@ export class NodeCryptoProvider } } - pbkdf2( - password: Buffer, - salt: Buffer, - iterations: number, - keylen = 64, - algo = 'sha512', - ): MaybeAsync { + pbkdf2(password: Buffer, salt: Buffer, iterations: number, keylen = 64, algo = 'sha512'): MaybeAsync { return new Promise((resolve, reject) => - pbkdf2( - password, - salt, - iterations, - keylen, - algo, - (err: Error | null, buf: Buffer) => - err !== null ? reject(err) : resolve(buf), + pbkdf2(password, salt, iterations, keylen, algo, (err: Error | null, buf: Buffer) => + err !== null ? reject(err) : resolve(buf), ), ) } diff --git a/packages/core/src/utils/crypto/password.ts b/packages/core/src/utils/crypto/password.ts index 2a7c08bc..b1219295 100644 --- a/packages/core/src/utils/crypto/password.ts +++ b/packages/core/src/utils/crypto/password.ts @@ -23,15 +23,10 @@ export async function computePasswordHash( salt1: Buffer, salt2: Buffer, ): Promise { - const SH = (data: Buffer, salt: Buffer) => - crypto.sha256(Buffer.concat([salt, data, salt])) - const PH1 = async (pwd: Buffer, salt1: Buffer, salt2: Buffer) => - SH(await SH(pwd, salt1), salt2) + const SH = (data: Buffer, salt: Buffer) => crypto.sha256(Buffer.concat([salt, data, salt])) + const PH1 = async (pwd: Buffer, salt1: Buffer, salt2: Buffer) => SH(await SH(pwd, salt1), salt2) const PH2 = async (pwd: Buffer, salt1: Buffer, salt2: Buffer) => - SH( - await crypto.pbkdf2(await PH1(pwd, salt1, salt2), salt1, 100000), - salt2, - ) + SH(await crypto.pbkdf2(await PH1(pwd, salt1, salt2), salt1, 100000), salt2) return PH2(password, salt1, salt2) } @@ -48,17 +43,9 @@ export async function computeNewPasswordHash( algo: tl.RawPasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow, password: string, ): Promise { - (algo as tl.Mutable).salt1 = Buffer.concat([ - algo.salt1, - randomBytes(32), - ]) + (algo as tl.Mutable).salt1 = Buffer.concat([algo.salt1, randomBytes(32)]) - const _x = await computePasswordHash( - crypto, - Buffer.from(password), - algo.salt1, - algo.salt2, - ) + const _x = await computePasswordHash(crypto, Buffer.from(password), algo.salt1, algo.salt2) const g = bigInt(algo.g) const p = bufferToBigInt(algo.p) @@ -82,8 +69,7 @@ export async function computeSrpParams( // nice naming thx durov if ( !request.currentAlgo || - request.currentAlgo._ !== - 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow' + request.currentAlgo._ !== 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow' ) { throw new MtUnsupportedError(`Unknown algo ${request.currentAlgo?._}`) } @@ -115,12 +101,7 @@ export async function computeSrpParams( // maybe, just maybe this will be a bit faster with some crypto providers /* k = */ crypto.sha256(Buffer.concat([algo.p, _g])), /* u = */ crypto.sha256(Buffer.concat([_gA, request.srpB])), - /* x = */ computePasswordHash( - crypto, - Buffer.from(password), - algo.salt1, - algo.salt2, - ), + /* x = */ computePasswordHash(crypto, Buffer.from(password), algo.salt1, algo.salt2), ]) const k = bufferToBigInt(_k) const u = bufferToBigInt(_u) diff --git a/packages/core/src/utils/deque.ts b/packages/core/src/utils/deque.ts index 00928d71..e043c3e4 100644 --- a/packages/core/src/utils/deque.ts +++ b/packages/core/src/utils/deque.ts @@ -2,13 +2,7 @@ const MIN_INITIAL_CAPACITY = 8 // System.arraycopy from java -function arraycopy( - src: T[], - srcPos: number, - dest: T[], - destPos: number, - length: number, -) { +function arraycopy(src: T[], srcPos: number, dest: T[], destPos: number, length: number) { for (let i = 0; i < length; i++) { dest[destPos + i] = src[srcPos + i] } @@ -29,10 +23,7 @@ export class Deque { protected _tail = 0 protected _capacity: number - constructor( - minCapacity = MIN_INITIAL_CAPACITY, - readonly maxLength = Infinity, - ) { + constructor(minCapacity = MIN_INITIAL_CAPACITY, readonly maxLength = Infinity) { let capacity = minCapacity if (capacity >= MIN_INITIAL_CAPACITY) { @@ -82,10 +73,7 @@ export class Deque { this._elements[this._tail] = item - if ( - (this._tail = (this._tail + 1) & (this._capacity - 1)) === - this._head - ) { + if ((this._tail = (this._tail + 1) & (this._capacity - 1)) === this._head) { this._resize() } @@ -97,8 +85,7 @@ export class Deque { pushFront(item: T): void { if (item === undefined) throw new Error('item can not be undefined') - this._elements[(this._head = (this._head - 1) & (this._capacity - 1))] = - item + this._elements[(this._head = (this._head - 1) & (this._capacity - 1))] = item if (this._head === this._tail) { this._resize() diff --git a/packages/core/src/utils/flood-control.ts b/packages/core/src/utils/flood-control.ts index 01b8c640..1a66ab85 100644 --- a/packages/core/src/utils/flood-control.ts +++ b/packages/core/src/utils/flood-control.ts @@ -52,24 +52,15 @@ export class FloodControl { limit.pos = this._events.length - limit.count } - while ( - limit.pos < this._events.length && - this._events[limit.pos] + limit.duration < now - ) { + while (limit.pos < this._events.length && this._events[limit.pos] + limit.duration < now) { limit.pos += 1 } if (limit.count + limit.pos < this._events.length) { - this._wakeupAt = Math.max( - this._wakeupAt, - this._events[limit.pos] + limit.duration, - ) + this._wakeupAt = Math.max(this._wakeupAt, this._events[limit.pos] + limit.duration) this._withoutUpdate = 0 } else { - this._withoutUpdate = Math.min( - this._withoutUpdate, - limit.count + limit.pos - this._events.length - 1, - ) + this._withoutUpdate = Math.min(this._withoutUpdate, limit.count + limit.pos - this._events.length - 1) } minPos = Math.min(minPos, limit.pos) diff --git a/packages/core/src/utils/function-utils.ts b/packages/core/src/utils/function-utils.ts index 8bc70f72..1b97d931 100644 --- a/packages/core/src/utils/function-utils.ts +++ b/packages/core/src/utils/function-utils.ts @@ -10,10 +10,7 @@ * @param func Function to throttle * @param delay Throttle delay */ -export function throttle( - func: () => void, - delay: number, -): () => void { +export function throttle(func: () => void, delay: number): () => void { let timeout: NodeJS.Timeout | null return function () { diff --git a/packages/core/src/utils/logger.ts b/packages/core/src/utils/logger.ts index a9e79295..f1f1c255 100644 --- a/packages/core/src/utils/logger.ts +++ b/packages/core/src/utils/logger.ts @@ -26,11 +26,7 @@ export class Logger { prefix = '' - constructor( - readonly mgr: LogManager, - readonly tag: string, - readonly parent: Logger = mgr, - ) { + constructor(readonly mgr: LogManager, readonly tag: string, readonly parent: Logger = mgr) { let hash = 0 for (let i = 0; i < tag.length; i++) { @@ -70,13 +66,7 @@ export class Logger { ) { let idx = 0 fmt = fmt.replace(FORMATTER_RE, (m) => { - if ( - m === '%h' || - m === '%b' || - m === '%j' || - m === '%J' || - m === '%l' - ) { + if (m === '%h' || m === '%b' || m === '%j' || m === '%J' || m === '%l') { let val = args[idx] args.splice(idx, 1) @@ -90,17 +80,13 @@ export class Logger { if (m === '%b') return String(Boolean(val)) if (m === '%j' || m === '%J') { - if (m === '%J') { val = [...(val as IterableIterator)] } + if (m === '%J') { + val = [...(val as IterableIterator)] + } return JSON.stringify(val, (k, v) => { - if ( - typeof v === 'object' && - v.type === 'Buffer' && - Array.isArray(v.data) - ) { - let str = Buffer.from( - v.data as number[], - ).toString('base64') + if (typeof v === 'object' && v.type === 'Buffer' && Array.isArray(v.data)) { + let str = Buffer.from(v.data as number[]).toString('base64') if (str.length > 300) { str = str.slice(0, 300) + '...' @@ -122,13 +108,7 @@ export class Logger { }) } - this.mgr.handler( - this.color, - level, - this.tag, - this.getPrefix() + fmt, - args, - ) + this.mgr.handler(this.color, level, this.tag, this.getPrefix() + fmt, args) } readonly error = this.log.bind(this, LogManager.ERROR) diff --git a/packages/core/src/utils/misc-utils.ts b/packages/core/src/utils/misc-utils.ts index aba2e9e4..de90a790 100644 --- a/packages/core/src/utils/misc-utils.ts +++ b/packages/core/src/utils/misc-utils.ts @@ -3,8 +3,7 @@ * * @param ms Number of ms to sleep */ -export const sleep = (ms: number): Promise => - new Promise((resolve) => setTimeout(resolve, ms)) +export const sleep = (ms: number): Promise => new Promise((resolve) => setTimeout(resolve, ms)) export function getRandomInt(top: number): number { return Math.floor(Math.random() * top) diff --git a/packages/core/src/utils/peer-utils.ts b/packages/core/src/utils/peer-utils.ts index 0926ccb0..fa433e15 100644 --- a/packages/core/src/utils/peer-utils.ts +++ b/packages/core/src/utils/peer-utils.ts @@ -50,21 +50,10 @@ 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') { @@ -153,9 +142,7 @@ export function markedPeerIdToBare(peerId: number): number { * Extracts all (cacheable) entities from a TlObject or a list of them. * Only checks `.user`, `.chat`, `.channel`, `.users` and `.chats` properties */ -export function* getAllPeersFrom( - obj: tl.TlObject | tl.TlObject[], -): Iterable { +export function* getAllPeersFrom(obj: tl.TlObject | tl.TlObject[]): Iterable { if (typeof obj !== 'object') return if (Array.isArray(obj)) { @@ -177,11 +164,7 @@ export function* getAllPeersFrom( return } - if ( - 'user' in obj && - typeof obj.user === 'object' && - obj.user._ === 'user' - ) { + if ('user' in obj && typeof obj.user === 'object' && obj.user._ === 'user') { yield obj.user } diff --git a/packages/core/src/utils/platform/logging.ts b/packages/core/src/utils/platform/logging.ts index 28b3ccbf..62451f94 100644 --- a/packages/core/src/utils/platform/logging.ts +++ b/packages/core/src/utils/platform/logging.ts @@ -24,36 +24,11 @@ const TAG_COLORS = [6, 2, 3, 4, 5, 1].map((i) => `\x1b[3${i};1m`) /** @internal */ export const _defaultLoggingHandler = isTty ? - ( - color: number, - level: number, - tag: string, - fmt: string, - args: unknown[], - ): void => { + (color: number, level: number, tag: string, fmt: string, args: unknown[]): void => { // eslint-disable-next-line no-console - console.log( - BASE_FORMAT + fmt, - new Date().toISOString(), - LEVEL_NAMES[level], - TAG_COLORS[color], - tag, - ...args, - ) + console.log(BASE_FORMAT + fmt, new Date().toISOString(), LEVEL_NAMES[level], TAG_COLORS[color], tag, ...args) } : - ( - color: number, - level: number, - tag: string, - fmt: string, - args: unknown[], - ): void => { + (color: number, level: number, tag: string, fmt: string, args: unknown[]): void => { // eslint-disable-next-line no-console - console.log( - BASE_FORMAT + fmt, - new Date().toISOString(), - LEVEL_NAMES[level], - tag, - ...args, - ) + console.log(BASE_FORMAT + fmt, new Date().toISOString(), LEVEL_NAMES[level], tag, ...args) } diff --git a/packages/core/src/utils/platform/logging.web.ts b/packages/core/src/utils/platform/logging.web.ts index 44946307..56ce2dd1 100644 --- a/packages/core/src/utils/platform/logging.web.ts +++ b/packages/core/src/utils/platform/logging.web.ts @@ -15,14 +15,7 @@ const COLORS = [ '#00ffff', '#ff00ff', ] -const TAG_COLORS = [ - '#44ffff', - '#44ff44', - '#ffff44', - '#4444ff', - '#ff44ff', - '#ff4444', -] +const TAG_COLORS = ['#44ffff', '#44ff44', '#ffff44', '#4444ff', '#ff44ff', '#ff4444'] /** @internal */ export const _defaultLoggingHandler = ( diff --git a/packages/core/src/utils/string-session.ts b/packages/core/src/utils/string-session.ts index 19badb0f..cb64de5d 100644 --- a/packages/core/src/utils/string-session.ts +++ b/packages/core/src/utils/string-session.ts @@ -1,10 +1,5 @@ import { tl } from '@mtcute/tl' -import { - TlBinaryReader, - TlBinaryWriter, - TlReaderMap, - TlWriterMap, -} from '@mtcute/tl-runtime' +import { TlBinaryReader, TlBinaryWriter, TlReaderMap, TlWriterMap } from '@mtcute/tl-runtime' import { ITelegramStorage } from '../storage' import { MtArgumentError } from '../types' @@ -18,18 +13,13 @@ export interface StringSessionData { authKey: Buffer } -export function writeStringSession( - writerMap: TlWriterMap, - data: StringSessionData, -): string { +export function writeStringSession(writerMap: TlWriterMap, data: StringSessionData): string { const writer = TlBinaryWriter.alloc(writerMap, 512) const version = data.version if (version !== 1 && version !== 2) { - throw new MtArgumentError( - `Unsupported string session version: ${version}`, - ) + throw new MtArgumentError(`Unsupported string session version: ${version}`) } let flags = 0 @@ -63,10 +53,7 @@ export function writeStringSession( return encodeUrlSafeBase64(writer.result()) } -export function readStringSession( - readerMap: TlReaderMap, - data: string, -): StringSessionData { +export function readStringSession(readerMap: TlReaderMap, data: string): StringSessionData { const buf = parseUrlSafeBase64(data) const version = buf[0] @@ -83,14 +70,10 @@ export function readStringSession( const hasMedia = version >= 2 && Boolean(flags & 4) const primaryDc = reader.object() as tl.TypeDcOption - const primaryMediaDc = hasMedia ? - (reader.object() as tl.TypeDcOption) : - primaryDc + const primaryMediaDc = hasMedia ? (reader.object() as tl.TypeDcOption) : primaryDc if (primaryDc._ !== 'dcOption') { - throw new MtArgumentError( - `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/type-assertions.ts b/packages/core/src/utils/type-assertions.ts index 60c66341..fba532e4 100644 --- a/packages/core/src/utils/type-assertions.ts +++ b/packages/core/src/utils/type-assertions.ts @@ -22,9 +22,7 @@ export function isPresent(t: T | undefined | null | void): t is T { * ``` */ export function hasPresentKey(k: K) { - return function ( - a: T & { [k in K]?: V | null }, - ): a is T & { [k in K]: V } { + return function (a: T & { [k in K]?: V | null }): a is T & { [k in K]: V } { return a[k] !== undefined && a[k] !== null } } @@ -46,13 +44,8 @@ export function hasPresentKey(k: K) { * files[0].imageUrl // TS will know this is present, because already it excluded the other union members. * ``` */ -export function hasValueAtKey( - k: K, - v: V, -) { - return function ( - a: T & { [k in K]: unknown }, - ): a is T & { [k in K]: V } { +export function hasValueAtKey(k: K, v: V) { + return function (a: T & { [k in K]: unknown }): a is T & { [k in K]: V } { return a[k] === v } } diff --git a/packages/core/tests/bigint-utils.spec.ts b/packages/core/tests/bigint-utils.spec.ts index 64ce2c64..ac8ec14f 100644 --- a/packages/core/tests/bigint-utils.spec.ts +++ b/packages/core/tests/bigint-utils.spec.ts @@ -7,93 +7,35 @@ import { bigIntToBuffer, bufferToBigInt } from '../utils' // since bigIntToBuffer is a tiny wrapper over writeBigInt, no need to test it individually describe('bigIntToBuffer', () => { it('should handle writing to BE', () => { - expect([...bigIntToBuffer(bigInt('10495708'), 0, false)]).eql([ - 0xa0, 0x26, 0xdc, + expect([...bigIntToBuffer(bigInt('10495708'), 0, false)]).eql([0xa0, 0x26, 0xdc]) + expect([...bigIntToBuffer(bigInt('10495708'), 4, false)]).eql([0x00, 0xa0, 0x26, 0xdc]) + expect([...bigIntToBuffer(bigInt('10495708'), 8, false)]).eql([0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x26, 0xdc]) + expect([...bigIntToBuffer(bigInt('3038102549'), 4, false)]).eql([0xb5, 0x15, 0xc4, 0x15]) + expect([...bigIntToBuffer(bigInt('9341376580368336208'), 8, false)]).eql([ + ...Buffer.from('81A33C81D2020550', 'hex'), ]) - expect([...bigIntToBuffer(bigInt('10495708'), 4, false)]).eql([ - 0x00, 0xa0, 0x26, 0xdc, - ]) - expect([...bigIntToBuffer(bigInt('10495708'), 8, false)]).eql([ - 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x26, 0xdc, - ]) - expect([...bigIntToBuffer(bigInt('3038102549'), 4, false)]).eql([ - 0xb5, 0x15, 0xc4, 0x15, - ]) - expect([ - ...bigIntToBuffer(bigInt('9341376580368336208'), 8, false), - ]).eql([...Buffer.from('81A33C81D2020550', 'hex')]) }) it('should handle writing to LE', () => { - expect([...bigIntToBuffer(bigInt('10495708'), 0, true)]).eql([ - 0xdc, 0x26, 0xa0, + expect([...bigIntToBuffer(bigInt('10495708'), 0, true)]).eql([0xdc, 0x26, 0xa0]) + expect([...bigIntToBuffer(bigInt('10495708'), 4, true)]).eql([0xdc, 0x26, 0xa0, 0x00]) + expect([...bigIntToBuffer(bigInt('10495708'), 8, true)]).eql([0xdc, 0x26, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00]) + expect([...bigIntToBuffer(bigInt('3038102549'), 4, true)]).eql([0x15, 0xc4, 0x15, 0xb5]) + expect([...bigIntToBuffer(bigInt('9341376580368336208'), 8, true)]).eql([ + ...Buffer.from('81A33C81D2020550', 'hex').reverse(), ]) - expect([...bigIntToBuffer(bigInt('10495708'), 4, true)]).eql([ - 0xdc, 0x26, 0xa0, 0x00, - ]) - expect([...bigIntToBuffer(bigInt('10495708'), 8, true)]).eql([ - 0xdc, 0x26, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, - ]) - expect([...bigIntToBuffer(bigInt('3038102549'), 4, true)]).eql([ - 0x15, 0xc4, 0x15, 0xb5, - ]) - expect([...bigIntToBuffer(bigInt('9341376580368336208'), 8, true)]).eql( - [...Buffer.from('81A33C81D2020550', 'hex').reverse()], - ) }) }) describe('bufferToBigInt', () => { it('should handle reading BE', () => { - expect( - bufferToBigInt( - Buffer.from([0xa0, 0x26, 0xdc]), - 0, - 3, - false, - ).toString(), - ).eq('10495708') - expect( - bufferToBigInt( - Buffer.from([0x00, 0xa0, 0x26, 0xdc]), - 0, - 4, - false, - ).toString(), - ).eq('10495708') - expect( - bufferToBigInt( - Buffer.from([0xb5, 0x15, 0xc4, 0x15]), - 0, - 4, - false, - ).toString(), - ).eq('3038102549') + expect(bufferToBigInt(Buffer.from([0xa0, 0x26, 0xdc]), 0, 3, false).toString()).eq('10495708') + expect(bufferToBigInt(Buffer.from([0x00, 0xa0, 0x26, 0xdc]), 0, 4, false).toString()).eq('10495708') + expect(bufferToBigInt(Buffer.from([0xb5, 0x15, 0xc4, 0x15]), 0, 4, false).toString()).eq('3038102549') }) it('should handle reading LE', () => { - expect( - bufferToBigInt( - Buffer.from([0xdc, 0x26, 0xa0]), - 0, - 3, - true, - ).toString(), - ).eq('10495708') - expect( - bufferToBigInt( - Buffer.from([0xdc, 0x26, 0xa0, 0x00]), - 0, - 4, - true, - ).toString(), - ).eq('10495708') - expect( - bufferToBigInt( - Buffer.from([0x15, 0xc4, 0x15, 0xb5]), - 0, - 4, - true, - ).toString(), - ).eq('3038102549') + expect(bufferToBigInt(Buffer.from([0xdc, 0x26, 0xa0]), 0, 3, true).toString()).eq('10495708') + expect(bufferToBigInt(Buffer.from([0xdc, 0x26, 0xa0, 0x00]), 0, 4, true).toString()).eq('10495708') + expect(bufferToBigInt(Buffer.from([0x15, 0xc4, 0x15, 0xb5]), 0, 4, true).toString()).eq('3038102549') }) }) diff --git a/packages/core/tests/buffer-utils.spec.ts b/packages/core/tests/buffer-utils.spec.ts index 5ef51241..788b606d 100644 --- a/packages/core/tests/buffer-utils.spec.ts +++ b/packages/core/tests/buffer-utils.spec.ts @@ -14,14 +14,12 @@ import { describe('buffersEqual', () => { it('should return true for equal buffers', () => { expect(buffersEqual(Buffer.from([]), Buffer.from([]))).is.true - expect(buffersEqual(Buffer.from([1, 2, 3]), Buffer.from([1, 2, 3]))).is - .true + expect(buffersEqual(Buffer.from([1, 2, 3]), Buffer.from([1, 2, 3]))).is.true }) it('should return false for non-equal buffers', () => { expect(buffersEqual(Buffer.from([1]), Buffer.from([]))).is.false - expect(buffersEqual(Buffer.from([1, 2, 3]), Buffer.from([1, 2, 4]))).is - .false + expect(buffersEqual(Buffer.from([1, 2, 3]), Buffer.from([1, 2, 4]))).is.false }) }) @@ -116,21 +114,15 @@ describe('cloneBuffer', () => { describe('parseUrlSafeBase64', () => { it('should parse url-safe base64', () => { - expect(parseUrlSafeBase64('qu7d8aGTeuF6-g').toString('hex')).eq( - 'aaeeddf1a1937ae17afa', - ) + expect(parseUrlSafeBase64('qu7d8aGTeuF6-g').toString('hex')).eq('aaeeddf1a1937ae17afa') }) it('should parse normal base64', () => { - expect(parseUrlSafeBase64('qu7d8aGTeuF6+g==').toString('hex')).eq( - 'aaeeddf1a1937ae17afa', - ) + expect(parseUrlSafeBase64('qu7d8aGTeuF6+g==').toString('hex')).eq('aaeeddf1a1937ae17afa') }) }) describe('encodeUrlSafeBase64', () => { it('should encode to url-safe base64', () => { - expect( - encodeUrlSafeBase64(Buffer.from('aaeeddf1a1937ae17afa', 'hex')), - ).eq('qu7d8aGTeuF6-g') + expect(encodeUrlSafeBase64(Buffer.from('aaeeddf1a1937ae17afa', 'hex'))).eq('qu7d8aGTeuF6-g') }) }) diff --git a/packages/core/tests/crypto-providers.spec.ts b/packages/core/tests/crypto-providers.spec.ts index d30fe4d7..d1b0b3a9 100644 --- a/packages/core/tests/crypto-providers.spec.ts +++ b/packages/core/tests/crypto-providers.spec.ts @@ -1,23 +1,15 @@ import { expect } from 'chai' import { describe, it } from 'mocha' -import { - ForgeCryptoProvider, - ICryptoProvider, - NodeCryptoProvider, -} from '../utils' +import { ForgeCryptoProvider, ICryptoProvider, NodeCryptoProvider } from '../utils' export function testCryptoProvider(c: ICryptoProvider): void { it('should calculate sha1', async () => { - expect((await c.sha1(Buffer.from(''))).toString('hex')).to.eq( - 'da39a3ee5e6b4b0d3255bfef95601890afd80709', + expect((await c.sha1(Buffer.from(''))).toString('hex')).to.eq('da39a3ee5e6b4b0d3255bfef95601890afd80709') + expect((await c.sha1(Buffer.from('hello'))).toString('hex')).to.eq('aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d') + expect((await c.sha1(Buffer.from('aebb1f', 'hex'))).toString('hex')).to.eq( + '62849d15c5dea495916c5eea8dba5f9551288850', ) - expect((await c.sha1(Buffer.from('hello'))).toString('hex')).to.eq( - 'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d', - ) - expect( - (await c.sha1(Buffer.from('aebb1f', 'hex'))).toString('hex'), - ).to.eq('62849d15c5dea495916c5eea8dba5f9551288850') }) it('should calculate sha256', async () => { @@ -27,9 +19,7 @@ export function testCryptoProvider(c: ICryptoProvider): void { expect((await c.sha256(Buffer.from('hello'))).toString('hex')).to.eq( '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824', ) - expect( - (await c.sha256(Buffer.from('aebb1f', 'hex'))).toString('hex'), - ).to.eq( + expect((await c.sha256(Buffer.from('aebb1f', 'hex'))).toString('hex')).to.eq( '2d29658aba48f2b286fe8bbddb931b7ad297e5adb5b9a6fc3aab67ef7fbf4e80', ) }) @@ -37,132 +27,70 @@ export function testCryptoProvider(c: ICryptoProvider): void { it('should calculate hmac-sha256', async () => { const key = Buffer.from('aaeeff', 'hex') - expect( - (await c.hmacSha256(Buffer.from(''), key)).toString('hex'), - ).to.eq( + expect((await c.hmacSha256(Buffer.from(''), key)).toString('hex')).to.eq( '642711307c9e4437df09d6ebaa6bdc1b3a810c7f15c50fd1d0f8d7d5490f44dd', ) - expect( - (await c.hmacSha256(Buffer.from('hello'), key)).toString('hex'), - ).to.eq( + expect((await c.hmacSha256(Buffer.from('hello'), key)).toString('hex')).to.eq( '39b00bab151f9868e6501655c580b5542954711181243474d46b894703b1c1c2', ) - expect( - (await c.hmacSha256(Buffer.from('aebb1f', 'hex'), key)).toString( - 'hex', - ), - ).to.eq( + expect((await c.hmacSha256(Buffer.from('aebb1f', 'hex'), key)).toString('hex')).to.eq( 'a3a7273871808711cab17aba14f58e96f63f3ccfc5097d206f0f00ead2c3dd35', ) }) it('should derive pbkdf2 key', async () => { - expect( - ( - await c.pbkdf2( - Buffer.from('pbkdf2 test'), - Buffer.from('some salt'), - 10, - ) - ).toString('hex'), - ).to.eq( + expect((await c.pbkdf2(Buffer.from('pbkdf2 test'), Buffer.from('some salt'), 10)).toString('hex')).to.eq( 'e43276cfa27f135f261cec8ddcf593fd74ec251038e459c165461f2308f3a7235e0744ee1aed9710b00db28d1a2112e20fea3601c60e770ac57ffe6b33ca8be1', ) }) it('should encrypt and decrypt aes-ctr', async () => { let aes = c.createAesCtr( - Buffer.from( - 'd450aae0bf0060a4af1044886b42a13f7c506b35255d134a7e87ab3f23a9493b', - 'hex', - ), + Buffer.from('d450aae0bf0060a4af1044886b42a13f7c506b35255d134a7e87ab3f23a9493b', 'hex'), Buffer.from('0182de2bd789c295c3c6c875c5e9e190', 'hex'), true, ) - expect((await aes.encrypt(Buffer.from([1, 2, 3]))).toString('hex')).eq( - 'a5fea1', - ) - expect((await aes.encrypt(Buffer.from([1, 2, 3]))).toString('hex')).eq( - 'ab51ca', - ) - expect((await aes.encrypt(Buffer.from([1, 2, 3]))).toString('hex')).eq( - '365e5c', - ) - expect((await aes.encrypt(Buffer.from([1, 2, 3]))).toString('hex')).eq( - '4b94a9', - ) - expect((await aes.encrypt(Buffer.from([1, 2, 3]))).toString('hex')).eq( - '776387', - ) - expect((await aes.encrypt(Buffer.from([1, 2, 3]))).toString('hex')).eq( - 'c940be', - ) + expect((await aes.encrypt(Buffer.from([1, 2, 3]))).toString('hex')).eq('a5fea1') + expect((await aes.encrypt(Buffer.from([1, 2, 3]))).toString('hex')).eq('ab51ca') + expect((await aes.encrypt(Buffer.from([1, 2, 3]))).toString('hex')).eq('365e5c') + expect((await aes.encrypt(Buffer.from([1, 2, 3]))).toString('hex')).eq('4b94a9') + expect((await aes.encrypt(Buffer.from([1, 2, 3]))).toString('hex')).eq('776387') + expect((await aes.encrypt(Buffer.from([1, 2, 3]))).toString('hex')).eq('c940be') aes = c.createAesCtr( - Buffer.from( - 'd450aae0bf0060a4af1044886b42a13f7c506b35255d134a7e87ab3f23a9493b', - 'hex', - ), + Buffer.from('d450aae0bf0060a4af1044886b42a13f7c506b35255d134a7e87ab3f23a9493b', 'hex'), Buffer.from('0182de2bd789c295c3c6c875c5e9e190', 'hex'), false, ) - expect( - (await aes.decrypt(Buffer.from('a5fea1', 'hex'))).toString('hex'), - ).eq('010203') - expect( - (await aes.decrypt(Buffer.from('ab51ca', 'hex'))).toString('hex'), - ).eq('010203') - expect( - (await aes.decrypt(Buffer.from('365e5c', 'hex'))).toString('hex'), - ).eq('010203') - expect( - (await aes.decrypt(Buffer.from('4b94a9', 'hex'))).toString('hex'), - ).eq('010203') - expect( - (await aes.decrypt(Buffer.from('776387', 'hex'))).toString('hex'), - ).eq('010203') - expect( - (await aes.decrypt(Buffer.from('c940be', 'hex'))).toString('hex'), - ).eq('010203') + expect((await aes.decrypt(Buffer.from('a5fea1', 'hex'))).toString('hex')).eq('010203') + expect((await aes.decrypt(Buffer.from('ab51ca', 'hex'))).toString('hex')).eq('010203') + expect((await aes.decrypt(Buffer.from('365e5c', 'hex'))).toString('hex')).eq('010203') + expect((await aes.decrypt(Buffer.from('4b94a9', 'hex'))).toString('hex')).eq('010203') + expect((await aes.decrypt(Buffer.from('776387', 'hex'))).toString('hex')).eq('010203') + expect((await aes.decrypt(Buffer.from('c940be', 'hex'))).toString('hex')).eq('010203') }) it('should encrypt and decrypt aes-ige', async () => { const aes = c.createAesIge( - Buffer.from( - '5468697320697320616E20696D706C655468697320697320616E20696D706C65', - 'hex', - ), - Buffer.from( - '6D656E746174696F6E206F6620494745206D6F646520666F72204F70656E5353', - 'hex', - ), + Buffer.from('5468697320697320616E20696D706C655468697320697320616E20696D706C65', 'hex'), + Buffer.from('6D656E746174696F6E206F6620494745206D6F646520666F72204F70656E5353', 'hex'), ) expect( ( await aes.encrypt( - Buffer.from( - '99706487a1cde613bc6de0b6f24b1c7aa448c8b9c3403e3467a8cad89340f53b', - 'hex', - ), + Buffer.from('99706487a1cde613bc6de0b6f24b1c7aa448c8b9c3403e3467a8cad89340f53b', 'hex'), ) ).toString('hex'), - ).to.eq( - '792ea8ae577b1a66cb3bd92679b8030ca54ee631976bd3a04547fdcb4639fa69', - ) + ).to.eq('792ea8ae577b1a66cb3bd92679b8030ca54ee631976bd3a04547fdcb4639fa69') expect( ( await aes.decrypt( - Buffer.from( - '792ea8ae577b1a66cb3bd92679b8030ca54ee631976bd3a04547fdcb4639fa69', - 'hex', - ), + Buffer.from('792ea8ae577b1a66cb3bd92679b8030ca54ee631976bd3a04547fdcb4639fa69', 'hex'), ) ).toString('hex'), - ).to.eq( - '99706487a1cde613bc6de0b6f24b1c7aa448c8b9c3403e3467a8cad89340f53b', - ) + ).to.eq('99706487a1cde613bc6de0b6f24b1c7aa448c8b9c3403e3467a8cad89340f53b') }) } diff --git a/packages/core/tests/transport-codecs/intermediate-codec.spec.ts b/packages/core/tests/transport-codecs/intermediate-codec.spec.ts index 9b785ccc..ecda29ec 100644 --- a/packages/core/tests/transport-codecs/intermediate-codec.spec.ts +++ b/packages/core/tests/transport-codecs/intermediate-codec.spec.ts @@ -5,9 +5,7 @@ import { IntermediatePacketCodec, TransportError } from '../../src' describe('IntermediatePacketCodec', () => { it('should return correct tag', () => { - expect(new IntermediatePacketCodec().tag().toString('hex')).eq( - 'eeeeeeee', - ) + expect(new IntermediatePacketCodec().tag().toString('hex')).eq('eeeeeeee') }) it('should correctly parse immediate framing', (done) => { diff --git a/packages/dispatcher/src/callback-data-builder.ts b/packages/dispatcher/src/callback-data-builder.ts index 9aacd634..2585b784 100644 --- a/packages/dispatcher/src/callback-data-builder.ts +++ b/packages/dispatcher/src/callback-data-builder.ts @@ -86,9 +86,7 @@ export class CallbackDataBuilder { * * @param params */ - filter( - params: Partial>>, - ): UpdateFilter< + filter(params: Partial>>): UpdateFilter< CallbackQuery, { match: Record @@ -106,22 +104,14 @@ export class CallbackDataBuilder { const value = params[field] if (Array.isArray(value)) { - parts.push( - `(${value - .map((i) => (typeof i === 'string' ? i : i.source)) - .join('|')})`, - ) + parts.push(`(${value.map((i) => (typeof i === 'string' ? i : i.source)).join('|')})`) } else { // noinspection SuspiciousTypeOfGuard - parts.push( - typeof value === 'string' ? value : (value as RegExp).source, - ) + parts.push(typeof value === 'string' ? value : (value as RegExp).source) } }) - const regex = new RegExp( - `^${this.prefix}${this.sep}${parts.join(this.sep)}$`, - ) + const regex = new RegExp(`^${this.prefix}${this.sep}${parts.join(this.sep)}$`) return (query) => { const m = query.dataStr?.match(regex) diff --git a/packages/dispatcher/src/dispatcher.ts b/packages/dispatcher/src/dispatcher.ts index f43fcb00..9c06d224 100644 --- a/packages/dispatcher/src/dispatcher.ts +++ b/packages/dispatcher/src/dispatcher.ts @@ -49,22 +49,14 @@ import { } from './handler' // end-codegen-imports import { PropagationAction } from './propagation' -import { - defaultStateKeyDelegate, - IStateStorage, - StateKeyDelegate, - UpdateState, -} from './state' +import { defaultStateKeyDelegate, IStateStorage, StateKeyDelegate, UpdateState } from './state' import { MtArgumentError } from '@mtcute/core' /** * Updates dispatcher */ export class Dispatcher { - private _groups: Record< - number, - Record - > = {} + private _groups: Record> = {} private _groupsOrder: number[] = [] private _client?: TelegramClient @@ -77,9 +69,7 @@ export class Dispatcher { private _sceneScoped?: boolean private _storage?: State extends never ? undefined : IStateStorage - private _stateKeyDelegate?: State extends never - ? undefined - : StateKeyDelegate + private _stateKeyDelegate?: State extends never ? undefined : StateKeyDelegate private _customStateKeyDelegate?: StateKeyDelegate private _customStorage?: IStateStorage @@ -87,18 +77,18 @@ export class Dispatcher { private _errorHandler?: ( err: Error, update: ParsedUpdate & T, - state?: UpdateState + state?: UpdateState, ) => MaybeAsync private _preUpdateHandler?: ( update: ParsedUpdate & T, - state?: UpdateState + state?: UpdateState, ) => MaybeAsync private _postUpdateHandler?: ( handled: boolean, update: ParsedUpdate & T, - state?: UpdateState + state?: UpdateState, ) => MaybeAsync /** @@ -115,14 +105,11 @@ export class Dispatcher { * Create a new dispatcher and bind it to client and optionally * FSM storage */ - constructor( - client: TelegramClient, - ...args: State extends never ? [] : [IStateStorage, StateKeyDelegate?] - ) + constructor(client: TelegramClient, ...args: State extends never ? [] : [IStateStorage, StateKeyDelegate?]) constructor( client?: TelegramClient | IStateStorage | StateKeyDelegate, storage?: IStateStorage | StateKeyDelegate, - key?: StateKeyDelegate + key?: StateKeyDelegate, ) { this.dispatchRawUpdate = this.dispatchRawUpdate.bind(this) this.dispatchUpdate = this.dispatchUpdate.bind(this) @@ -133,8 +120,7 @@ export class Dispatcher { if (storage) { this._storage = storage as any - this._stateKeyDelegate = (key ?? - defaultStateKeyDelegate) as any + this._stateKeyDelegate = (key ?? defaultStateKeyDelegate) as any } } else if (typeof client === 'function') { // is StateKeyDelegate @@ -194,17 +180,12 @@ export class Dispatcher { * @param update Update to process * @param peers Peers index */ - dispatchRawUpdate( - update: tl.TypeUpdate | tl.TypeMessage, - peers: PeersIndex - ): void { + dispatchRawUpdate(update: tl.TypeUpdate | tl.TypeMessage, peers: PeersIndex): void { if (!this._client) return // order does not matter in the dispatcher, // so we can handle each update in its own task - this.dispatchRawUpdateNow(update, peers).catch((err) => - this._client!['_emitError'](err) - ) + this.dispatchRawUpdateNow(update, peers).catch((err) => this._client!['_emitError'](err)) } /** @@ -219,10 +200,7 @@ export class Dispatcher { * @param peers Peers map * @returns Whether the update was handled */ - async dispatchRawUpdateNow( - update: tl.TypeUpdate | tl.TypeMessage, - peers: PeersIndex - ): Promise { + async dispatchRawUpdateNow(update: tl.TypeUpdate | tl.TypeMessage, peers: PeersIndex): Promise { if (!this._client) return false let handled = false @@ -236,10 +214,7 @@ export class Dispatcher { for (const h of handlers) { let result: void | PropagationAction - if ( - !h.check || - (await h.check(this._client, update, peers)) - ) { + if (!h.check || (await h.check(this._client, update, peers))) { result = await h.callback(this._client, update, peers) handled = true } else continue @@ -280,9 +255,7 @@ export class Dispatcher { // order does not matter in the dispatcher, // so we can handle each update in its own task - this.dispatchUpdateNow(update).catch((err) => - this._client!['_emitError'](err) - ) + this.dispatchUpdateNow(update).catch((err) => this._client!['_emitError'](err)) } /** @@ -305,7 +278,7 @@ export class Dispatcher { // this is getting a bit crazy lol parsedState?: UpdateState | null, parsedScene?: string | null, - forceScene?: true + forceScene?: true, ): Promise { if (!this._client) return false @@ -313,9 +286,7 @@ export class Dispatcher { if ( this._storage && this._scenes && - (update.name === 'new_message' || - update.name === 'edit_message' || - update.name === 'callback_query') + (update.name === 'new_message' || update.name === 'edit_message' || update.name === 'callback_query') ) { // no need to fetch scene if there are no registered scenes @@ -343,21 +314,14 @@ export class Dispatcher { return false } - return this._scenes[parsedScene]._dispatchUpdateNowImpl( - update, - parsedState, - parsedScene, - true - ) + return this._scenes[parsedScene]._dispatchUpdateNowImpl(update, parsedState, parsedScene, true) } } if (parsedState === undefined) { if ( this._storage && - (update.name === 'new_message' || - update.name === 'edit_message' || - update.name === 'callback_query') + (update.name === 'new_message' || update.name === 'edit_message' || update.name === 'callback_query') ) { const key = await this._stateKeyDelegate!(update.data) @@ -366,9 +330,7 @@ export class Dispatcher { if ( !this._customStateKeyDelegate || - (customKey = await this._customStateKeyDelegate( - update.data - )) + (customKey = await this._customStateKeyDelegate(update.data)) ) { parsedState = new UpdateState( this._storage, @@ -376,7 +338,7 @@ export class Dispatcher { this._scene ?? null, this._sceneScoped, this._customStorage, - customKey + customKey, ) } } else { @@ -405,26 +367,14 @@ export class Dispatcher { if (update.name in group) { // raw is not handled here, so we can safely assume this - const handlers = group[update.name] as Exclude< - UpdateHandler, - RawUpdateHandler - >[] + const handlers = group[update.name] as Exclude[] try { for (const h of handlers) { let result: void | PropagationAction - if ( - !h.check || - (await h.check( - update.data as any, - parsedState as never - )) - ) { - result = await h.callback( - update.data as any, - parsedState as never - ) + if (!h.check || (await h.check(update.data as any, parsedState as never))) { + result = await h.callback(update.data as any, parsedState as never) handled = true } else continue @@ -439,27 +389,16 @@ export class Dispatcher { case 'scene': { if (!parsedState) { - throw new MtArgumentError( - 'Cannot use ToScene without state' - ) + throw new MtArgumentError('Cannot use ToScene without state') } const scene = parsedState['_scene'] if (!scene) { - throw new MtArgumentError( - 'Cannot use ToScene without entering a scene' - ) + throw new MtArgumentError('Cannot use ToScene without entering a scene') } - return this._scenes![ - scene - ]._dispatchUpdateNowImpl( - update, - undefined, - scene, - true - ) + return this._scenes![scene]._dispatchUpdateNowImpl(update, undefined, scene, true) } } @@ -467,11 +406,7 @@ export class Dispatcher { } } catch (e: any) { if (this._errorHandler) { - const handled = await this._errorHandler( - e, - update, - parsedState as never - ) + const handled = await this._errorHandler(e, update, parsedState as never) if (!handled) throw e } else { throw e @@ -521,10 +456,7 @@ export class Dispatcher { * @param group Handler group index (-1 to affect all groups) * @internal */ - removeUpdateHandler( - handler: UpdateHandler | UpdateHandler['name'] | 'all', - group = 0 - ): void { + removeUpdateHandler(handler: UpdateHandler | UpdateHandler['name'] | 'all', group = 0): void { if (group !== -1 && !(group in this._groups)) { return } @@ -572,12 +504,8 @@ export class Dispatcher { */ onError( handler: - | (( - err: Error, - update: ParsedUpdate & T, - state?: UpdateState - ) => MaybeAsync) - | null + | ((err: Error, update: ParsedUpdate & T, state?: UpdateState) => MaybeAsync) + | null, ): void { if (handler) this._errorHandler = handler else this._errorHandler = undefined @@ -599,9 +527,9 @@ export class Dispatcher { handler: | (( update: ParsedUpdate & T, - state?: UpdateState + state?: UpdateState, ) => MaybeAsync) - | null + | null, ): void { if (handler) this._preUpdateHandler = handler else this._preUpdateHandler = undefined @@ -621,12 +549,8 @@ export class Dispatcher { */ onPostUpdate( handler: - | (( - handled: boolean, - update: ParsedUpdate & T, - state?: UpdateState - ) => MaybeAsync) - | null + | ((handled: boolean, update: ParsedUpdate & T, state?: UpdateState) => MaybeAsync) + | null, ): void { if (handler) this._postUpdateHandler = handler else this._postUpdateHandler = undefined @@ -639,7 +563,7 @@ export class Dispatcher { propagateErrorToParent( err: Error, update: ParsedUpdate, - state?: UpdateState + state?: UpdateState, ): MaybeAsync { if (!this.parent) { throw new MtArgumentError('This dispatcher is not a child') @@ -667,7 +591,7 @@ export class Dispatcher { 'Provided dispatcher is ' + (child._parent ? 'already a child. Use parent.removeChild() before calling addChild()' - : 'already bound to a client. Use unbind() before calling addChild()') + : 'already bound to a client. Use unbind() before calling addChild()'), ) } @@ -712,11 +636,7 @@ export class Dispatcher { * @param scene Dispatcher representing the scene * @param scoped Whether to use scoped FSM storage for the scene */ - addScene( - uid: SceneName, - scene: Dispatcher, - scoped: false - ): void + addScene(uid: SceneName, scene: Dispatcher, scoped: false): void /** * Add a dispatcher as a scene with a scoped state * @@ -730,22 +650,12 @@ export class Dispatcher { * @param scene Dispatcher representing the scene * @param scoped Whether to use scoped FSM storage for the scene (defaults to `true`) */ - addScene( - uid: SceneName, - scene: Dispatcher, - scoped?: true - ): void - addScene( - uid: SceneName, - scene: Dispatcher, - scoped = true - ): void { + addScene(uid: SceneName, scene: Dispatcher, scoped?: true): void + addScene(uid: SceneName, scene: Dispatcher, scoped = true): void { if (!this._scenes) this._scenes = {} if (uid in this._scenes) { - throw new MtArgumentError( - `Scene with UID ${uid} is already registered!` - ) + throw new MtArgumentError(`Scene with UID ${uid} is already registered!`) } if (uid[0] === '$') { @@ -753,9 +663,7 @@ export class Dispatcher { } if (scene._scene) { - throw new MtArgumentError( - `This dispatcher is already registered as scene ${scene._scene}` - ) + throw new MtArgumentError(`This dispatcher is already registered as scene ${scene._scene}`) } this._prepareChild(scene) @@ -804,9 +712,7 @@ export class Dispatcher { */ extend(other: Dispatcher): void { if (other._customStorage || other._customStateKeyDelegate) { - throw new MtArgumentError( - 'Provided dispatcher has custom storage and cannot be extended from.' - ) + throw new MtArgumentError('Provided dispatcher has custom storage and cannot be extended from.') } other._groupsOrder.forEach((group) => { @@ -844,11 +750,7 @@ export class Dispatcher { delete myScenes[key] } - this.addScene( - key as any, - myScenes[key] as any, - myScenes[key]._sceneScoped as any - ) + this.addScene(key as any, myScenes[key] as any, myScenes[key]._sceneScoped as any) }) } @@ -877,9 +779,7 @@ export class Dispatcher { dp._groups[idx] = {} as any Object.keys(this._groups[idx]).forEach((type) => { - dp._groups[idx][type as UpdateHandler['name']] = [ - ...this._groups[idx][type as UpdateHandler['name']], - ] + dp._groups[idx][type as UpdateHandler['name']] = [...this._groups[idx][type as UpdateHandler['name']]] }) }) @@ -901,7 +801,7 @@ export class Dispatcher { key as any, scene as any, - this._scenes![key]._sceneScoped as any + this._scenes![key]._sceneScoped as any, ) }) } @@ -931,26 +831,14 @@ export class Dispatcher { * @param object Object for which the state should be fetched * @template S State type, defaults to dispatcher's state type. Only checked at compile-time */ - getState( - object: Parameters[0] - ): Promise> - getState( - object: string | Parameters[0] - ): MaybeAsync> { + getState(object: Parameters[0]): Promise> + getState(object: string | Parameters[0]): MaybeAsync> { if (!this._storage) { - throw new MtArgumentError( - 'Cannot use getUpdateState() filter without state storage' - ) + throw new MtArgumentError('Cannot use getUpdateState() filter without state storage') } if (typeof object === 'string') { - return new UpdateState( - this._storage, - object, - this._scene ?? null, - this._sceneScoped, - this._customStorage - ) + return new UpdateState(this._storage, object, this._scene ?? null, this._sceneScoped, this._customStorage) } return Promise.resolve(this._stateKeyDelegate!(object)).then((key) => { @@ -959,33 +847,23 @@ export class Dispatcher { } if (!this._customStateKeyDelegate) { + return new UpdateState(this._storage!, key, this._scene ?? null, this._sceneScoped, this._customStorage) + } + + return Promise.resolve(this._customStateKeyDelegate(object)).then((customKey) => { + if (!customKey) { + throw new MtArgumentError('Cannot derive custom key from given object') + } + return new UpdateState( this._storage!, key, this._scene ?? null, this._sceneScoped, - this._customStorage + this._customStorage, + customKey, ) - } - - return Promise.resolve(this._customStateKeyDelegate(object)).then( - (customKey) => { - if (!customKey) { - throw new MtArgumentError( - 'Cannot derive custom key from given object' - ) - } - - return new UpdateState( - this._storage!, - key, - this._scene ?? null, - this._sceneScoped, - this._customStorage, - customKey - ) - } - ) + }) }) } @@ -995,9 +873,7 @@ export class Dispatcher { * This will load the state for the given object * ignoring local custom storage, key delegate and scene scope. */ - getGlobalState( - object: Parameters[0] - ): Promise> { + getGlobalState(object: Parameters[0]): Promise> { if (!this._parent) { throw new MtArgumentError('This dispatcher does not have a parent') } @@ -1007,30 +883,20 @@ export class Dispatcher { throw new MtArgumentError('Cannot derive key from given object') } - return new UpdateState( - this._storage!, - key, - this._scene ?? null, - false - ) + return new UpdateState(this._storage!, key, this._scene ?? null, false) }) } // addUpdateHandler convenience wrappers // - private _addKnownHandler( - name: UpdateHandler['name'], - filter: any, - handler?: any, - group?: number - ): void { + private _addKnownHandler(name: UpdateHandler['name'], filter: any, handler?: any, group?: number): void { if (typeof handler === 'number' || typeof handler === 'undefined') { this.addUpdateHandler( { name, callback: filter, }, - handler + handler, ) } else { this.addUpdateHandler( @@ -1039,7 +905,7 @@ export class Dispatcher { callback: handler, check: filter, }, - group + group, ) } } @@ -1059,11 +925,7 @@ export class Dispatcher { * @param handler Raw update handler * @param group Handler group index */ - onRawUpdate( - filter: RawUpdateHandler['check'], - handler: RawUpdateHandler['callback'], - group?: number - ): void + onRawUpdate(filter: RawUpdateHandler['check'], handler: RawUpdateHandler['callback'], group?: number): void /** @internal */ onRawUpdate(filter: any, handler?: any, group?: number): void { @@ -1079,11 +941,8 @@ export class Dispatcher { * @param group Handler group index */ onNewMessage( - handler: NewMessageHandler< - Message, - State extends never ? never : UpdateState - >['callback'], - group?: number + handler: NewMessageHandler>['callback'], + group?: number, ): void /** @@ -1099,7 +958,7 @@ export class Dispatcher { filters.Modify, State extends never ? never : UpdateState >['callback'], - group?: number + group?: number, ): void /** @@ -1115,7 +974,7 @@ export class Dispatcher { filters.Modify, State extends never ? never : UpdateState >['callback'], - group?: number + group?: number, ): void /** @internal */ @@ -1130,11 +989,8 @@ export class Dispatcher { * @param group Handler group index */ onEditMessage( - handler: EditMessageHandler< - Message, - State extends never ? never : UpdateState - >['callback'], - group?: number + handler: EditMessageHandler>['callback'], + group?: number, ): void /** @@ -1150,7 +1006,7 @@ export class Dispatcher { filters.Modify, State extends never ? never : UpdateState >['callback'], - group?: number + group?: number, ): void /** @@ -1166,7 +1022,7 @@ export class Dispatcher { filters.Modify, State extends never ? never : UpdateState >['callback'], - group?: number + group?: number, ): void /** @internal */ @@ -1180,10 +1036,7 @@ export class Dispatcher { * @param handler Delete message handler * @param group Handler group index */ - onDeleteMessage( - handler: DeleteMessageHandler['callback'], - group?: number - ): void + onDeleteMessage(handler: DeleteMessageHandler['callback'], group?: number): void /** * Register a delete message handler with a filter @@ -1194,10 +1047,8 @@ export class Dispatcher { */ onDeleteMessage( filter: UpdateFilter, - handler: DeleteMessageHandler< - filters.Modify - >['callback'], - group?: number + handler: DeleteMessageHandler>['callback'], + group?: number, ): void /** @internal */ @@ -1211,10 +1062,7 @@ export class Dispatcher { * @param handler Chat member update handler * @param group Handler group index */ - onChatMemberUpdate( - handler: ChatMemberUpdateHandler['callback'], - group?: number - ): void + onChatMemberUpdate(handler: ChatMemberUpdateHandler['callback'], group?: number): void /** * Register a chat member update handler with a filter @@ -1225,10 +1073,8 @@ export class Dispatcher { */ onChatMemberUpdate( filter: UpdateFilter, - handler: ChatMemberUpdateHandler< - filters.Modify - >['callback'], - group?: number + handler: ChatMemberUpdateHandler>['callback'], + group?: number, ): void /** @internal */ @@ -1253,10 +1099,8 @@ export class Dispatcher { */ onInlineQuery( filter: UpdateFilter, - handler: InlineQueryHandler< - filters.Modify - >['callback'], - group?: number + handler: InlineQueryHandler>['callback'], + group?: number, ): void /** @internal */ @@ -1270,10 +1114,7 @@ export class Dispatcher { * @param handler Chosen inline result handler * @param group Handler group index */ - onChosenInlineResult( - handler: ChosenInlineResultHandler['callback'], - group?: number - ): void + onChosenInlineResult(handler: ChosenInlineResultHandler['callback'], group?: number): void /** * Register a chosen inline result handler with a filter @@ -1284,10 +1125,8 @@ export class Dispatcher { */ onChosenInlineResult( filter: UpdateFilter, - handler: ChosenInlineResultHandler< - filters.Modify - >['callback'], - group?: number + handler: ChosenInlineResultHandler>['callback'], + group?: number, ): void /** @internal */ @@ -1306,7 +1145,7 @@ export class Dispatcher { CallbackQuery, State extends never ? never : UpdateState >['callback'], - group?: number + group?: number, ): void /** @@ -1322,7 +1161,7 @@ export class Dispatcher { filters.Modify, State extends never ? never : UpdateState >['callback'], - group?: number + group?: number, ): void /** @@ -1338,7 +1177,7 @@ export class Dispatcher { filters.Modify, State extends never ? never : UpdateState >['callback'], - group?: number + group?: number, ): void /** @internal */ @@ -1364,7 +1203,7 @@ export class Dispatcher { onPollUpdate( filter: UpdateFilter, handler: PollUpdateHandler>['callback'], - group?: number + group?: number, ): void /** @internal */ @@ -1389,10 +1228,8 @@ export class Dispatcher { */ onPollVote( filter: UpdateFilter, - handler: PollVoteHandler< - filters.Modify - >['callback'], - group?: number + handler: PollVoteHandler>['callback'], + group?: number, ): void /** @internal */ @@ -1406,10 +1243,7 @@ export class Dispatcher { * @param handler User status update handler * @param group Handler group index */ - onUserStatusUpdate( - handler: UserStatusUpdateHandler['callback'], - group?: number - ): void + onUserStatusUpdate(handler: UserStatusUpdateHandler['callback'], group?: number): void /** * Register an user status update handler with a filter @@ -1420,10 +1254,8 @@ export class Dispatcher { */ onUserStatusUpdate( filter: UpdateFilter, - handler: UserStatusUpdateHandler< - filters.Modify - >['callback'], - group?: number + handler: UserStatusUpdateHandler>['callback'], + group?: number, ): void /** @internal */ @@ -1448,10 +1280,8 @@ export class Dispatcher { */ onUserTyping( filter: UpdateFilter, - handler: UserTypingHandler< - filters.Modify - >['callback'], - group?: number + handler: UserTypingHandler>['callback'], + group?: number, ): void /** @internal */ @@ -1476,10 +1306,8 @@ export class Dispatcher { */ onHistoryRead( filter: UpdateFilter, - handler: HistoryReadHandler< - filters.Modify - >['callback'], - group?: number + handler: HistoryReadHandler>['callback'], + group?: number, ): void /** @internal */ @@ -1504,10 +1332,8 @@ export class Dispatcher { */ onBotStopped( filter: UpdateFilter, - handler: BotStoppedHandler< - filters.Modify - >['callback'], - group?: number + handler: BotStoppedHandler>['callback'], + group?: number, ): void /** @internal */ @@ -1521,10 +1347,7 @@ export class Dispatcher { * @param handler Bot chat join request handler * @param group Handler group index */ - onBotChatJoinRequest( - handler: BotChatJoinRequestHandler['callback'], - group?: number - ): void + onBotChatJoinRequest(handler: BotChatJoinRequestHandler['callback'], group?: number): void /** * Register a bot chat join request handler with a filter @@ -1535,10 +1358,8 @@ export class Dispatcher { */ onBotChatJoinRequest( filter: UpdateFilter, - handler: BotChatJoinRequestHandler< - filters.Modify - >['callback'], - group?: number + handler: BotChatJoinRequestHandler>['callback'], + group?: number, ): void /** @internal */ @@ -1552,10 +1373,7 @@ export class Dispatcher { * @param handler Chat join request handler * @param group Handler group index */ - onChatJoinRequest( - handler: ChatJoinRequestHandler['callback'], - group?: number - ): void + onChatJoinRequest(handler: ChatJoinRequestHandler['callback'], group?: number): void /** * Register a chat join request handler with a filter @@ -1566,10 +1384,8 @@ export class Dispatcher { */ onChatJoinRequest( filter: UpdateFilter, - handler: ChatJoinRequestHandler< - filters.Modify - >['callback'], - group?: number + handler: ChatJoinRequestHandler>['callback'], + group?: number, ): void /** @internal */ @@ -1583,10 +1399,7 @@ export class Dispatcher { * @param handler Pre checkout query handler * @param group Handler group index */ - onPreCheckoutQuery( - handler: PreCheckoutQueryHandler['callback'], - group?: number - ): void + onPreCheckoutQuery(handler: PreCheckoutQueryHandler['callback'], group?: number): void /** * Register a pre checkout query handler with a filter @@ -1597,10 +1410,8 @@ export class Dispatcher { */ onPreCheckoutQuery( filter: UpdateFilter, - handler: PreCheckoutQueryHandler< - filters.Modify - >['callback'], - group?: number + handler: PreCheckoutQueryHandler>['callback'], + group?: number, ): void /** @internal */ diff --git a/packages/dispatcher/src/filters/bots.ts b/packages/dispatcher/src/filters/bots.ts index 954a2f72..d1003702 100644 --- a/packages/dispatcher/src/filters/bots.ts +++ b/packages/dispatcher/src/filters/bots.ts @@ -28,9 +28,7 @@ export const command = ( ): UpdateFilter => { if (!Array.isArray(commands)) commands = [commands] - commands = commands.map((i) => - typeof i === 'string' ? i.toLowerCase() : i, - ) + commands = commands.map((i) => (typeof i === 'string' ? i.toLowerCase() : i)) const argumentsRe = /(["'])(.*?)(? { if (typeof cmd !== 'string') cmd = cmd.source - commandsRe.push( - new RegExp( - `^(${cmd})(?:\\s|$|@([a-zA-Z0-9_]+?bot)(?:\\s|$))`, - caseSensitive ? '' : 'i', - ), - ) + commandsRe.push(new RegExp(`^(${cmd})(?:\\s|$|@([a-zA-Z0-9_]+?bot)(?:\\s|$))`, caseSensitive ? '' : 'i')) }) if (prefixes === null) prefixes = [] @@ -75,13 +68,11 @@ export const command = ( const match = m.slice(1, -1) // we use .replace to iterate over global regex, not to replace the text - withoutPrefix - .slice(m[0].length) - .replace(argumentsRe, ($0, $1, $2: string, $3: string) => { - match.push(($2 || $3 || '').replace(unescapeRe, '$1')) + withoutPrefix.slice(m[0].length).replace(argumentsRe, ($0, $1, $2: string, $3: string) => { + match.push(($2 || $3 || '').replace(unescapeRe, '$1')) - return '' - }) + return '' + }) ;(msg as Message & { command: string[] }).command = match return true @@ -106,9 +97,7 @@ export const start = and(chat('private'), command('start')) * If the parameter is a regex, groups are added to `msg.command`, * meaning that the first group is available in `msg.command[2]`. */ -export const deeplink = ( - params: MaybeArray, -): UpdateFilter => { +export const deeplink = (params: MaybeArray): UpdateFilter => { if (!Array.isArray(params)) { return and(start, (_msg: Message) => { const msg = _msg as Message & { command: string[] } diff --git a/packages/dispatcher/src/filters/chat.ts b/packages/dispatcher/src/filters/chat.ts index 981be0ac..eb10c0c7 100644 --- a/packages/dispatcher/src/filters/chat.ts +++ b/packages/dispatcher/src/filters/chat.ts @@ -22,9 +22,7 @@ export const chat = /** * Filter updates by chat ID(s) or username(s) */ -export const chatId = ( - id: MaybeArray, -): UpdateFilter => { +export const chatId = (id: MaybeArray): UpdateFilter => { if (Array.isArray(id)) { const index: Record = {} let matchSelf = false @@ -45,11 +43,7 @@ export const chatId = ( const chat = (upd as Exclude).chat - return ( - (matchSelf && chat.isSelf) || - chat.id in index || - chat.username! in index - ) + return (matchSelf && chat.isSelf) || chat.id in index || chat.username! in index } } @@ -69,10 +63,7 @@ export const chatId = ( return upd.peer.type === 'chat' && upd.peer.username === id } - return ( - (upd as Exclude).chat.username === - id - ) + return (upd as Exclude).chat.username === id } } diff --git a/packages/dispatcher/src/filters/logic.ts b/packages/dispatcher/src/filters/logic.ts index 475777d3..e6af9c1d 100644 --- a/packages/dispatcher/src/filters/logic.ts +++ b/packages/dispatcher/src/filters/logic.ts @@ -4,14 +4,7 @@ import { MaybeAsync } from '@mtcute/core' import { UpdateState } from '../state' -import { - ExtractBaseMany, - ExtractMod, - ExtractState, - Invert, - UnionToIntersection, - UpdateFilter, -} from './types' +import { ExtractBaseMany, ExtractMod, ExtractState, Invert, UnionToIntersection, UpdateFilter } from './types' /** * Filter that matches any update @@ -135,10 +128,7 @@ export function or( */ export function every[]>( ...fns: Filters -): UpdateFilter< - ExtractBaseMany, - UnionToIntersection> -> { +): UpdateFilter, UnionToIntersection>> { if (fns.length === 2) return and(fns[0], fns[1]) return (upd, state) => { @@ -185,11 +175,7 @@ export function every[]>( */ export function some[]>( ...fns: Filters -): UpdateFilter< - ExtractBaseMany, - ExtractMod, - ExtractState -> { +): UpdateFilter, ExtractMod, ExtractState> { if (fns.length === 2) return or(fns[0], fns[1]) return (upd, state) => { diff --git a/packages/dispatcher/src/filters/message.ts b/packages/dispatcher/src/filters/message.ts index a240a3d4..27a86c16 100644 --- a/packages/dispatcher/src/filters/message.ts +++ b/packages/dispatcher/src/filters/message.ts @@ -22,42 +22,30 @@ import { Modify, UpdateFilter } from './types' * * Messages sent to yourself (i.e. Saved Messages) are also "incoming" */ -export const incoming: UpdateFilter = (msg) => - !msg.isOutgoing +export const incoming: UpdateFilter = (msg) => !msg.isOutgoing /** * Filter outgoing messages. * * Messages sent to yourself (i.e. Saved Messages) are **not** "outgoing" */ -export const outgoing: UpdateFilter = (msg) => - msg.isOutgoing +export const outgoing: UpdateFilter = (msg) => msg.isOutgoing /** * Filter messages that are replies to some other message */ -export const reply: UpdateFilter = ( - msg, -) => msg.replyToMessageId !== null +export const reply: UpdateFilter = (msg) => msg.replyToMessageId !== null /** * Filter messages containing some media */ -export const media: UpdateFilter< - Message, - { media: Exclude } -> = (msg) => msg.media !== null +export const media: UpdateFilter }> = (msg) => msg.media !== null /** * Filter messages containing media of given type */ export const mediaOf = - ( - type: T, - ): UpdateFilter< - Message, - { media: Extract } - > => + (type: T): UpdateFilter }> => (msg) => msg.media?.type === type @@ -95,8 +83,7 @@ export const invoice = mediaOf('invoice') /** * Filter messages containing any location (live or static). */ -export const anyLocation: UpdateFilter = (msg) => - msg.media instanceof RawLocation +export const anyLocation: UpdateFilter = (msg) => msg.media instanceof RawLocation /** * Filter messages containing a document @@ -104,9 +91,7 @@ export const anyLocation: UpdateFilter = (msg) => * This will also match media like audio, video, voice * that also use Documents */ -export const anyDocument: UpdateFilter = ( - msg, -) => msg.media instanceof RawDocument +export const anyDocument: UpdateFilter = (msg) => msg.media instanceof RawDocument /** * Filter messages containing a simple video. @@ -124,8 +109,7 @@ export const video: UpdateFilter< } > } -> = (msg) => - msg.media?.type === 'video' && !msg.media.isAnimation && !msg.media.isRound +> = (msg) => msg.media?.type === 'video' && !msg.media.isAnimation && !msg.media.isRound /** * Filter messages containing an animation. @@ -144,8 +128,7 @@ export const animation: UpdateFilter< } > } -> = (msg) => - msg.media?.type === 'video' && msg.media.isAnimation && !msg.media.isRound +> = (msg) => msg.media?.type === 'video' && msg.media.isAnimation && !msg.media.isRound /** * Filter messages containing a round message (aka video note). @@ -161,8 +144,7 @@ export const roundMessage: UpdateFilter< } > } -> = (msg) => - msg.media?.type === 'video' && !msg.media.isAnimation && msg.media.isRound +> = (msg) => msg.media?.type === 'video' && !msg.media.isAnimation && msg.media.isRound /** * Filter messages containing a sticker by its type @@ -194,8 +176,7 @@ export const text: UpdateFilter< /** * Filter service messages */ -export const service: UpdateFilter = (msg) => - msg.isService +export const service: UpdateFilter = (msg) => msg.isService /** * Filter service messages by action type @@ -206,12 +187,7 @@ export const action = ['type']>( Message, { action: Extract - sender: T extends - | 'user_joined_link' - | 'user_removed' - | 'history_cleared' - | 'contact_joined' - | 'bot_allowed' + sender: T extends 'user_joined_link' | 'user_removed' | 'history_cleared' | 'contact_joined' | 'bot_allowed' ? User : User | Chat } diff --git a/packages/dispatcher/src/filters/text.ts b/packages/dispatcher/src/filters/text.ts index 62cf4613..57fee477 100644 --- a/packages/dispatcher/src/filters/text.ts +++ b/packages/dispatcher/src/filters/text.ts @@ -1,17 +1,10 @@ // ^^ will be looked into in MTQ-29 -import { - CallbackQuery, - ChosenInlineResult, - InlineQuery, - Message, -} from '@mtcute/client' +import { CallbackQuery, ChosenInlineResult, InlineQuery, Message } from '@mtcute/client' import { UpdateFilter } from './types' -function extractText( - obj: Message | InlineQuery | ChosenInlineResult | CallbackQuery, -): string | null { +function extractText(obj: Message | InlineQuery | ChosenInlineResult | CallbackQuery): string | null { if (obj.constructor === Message) { return obj.text } else if (obj.constructor === InlineQuery) { @@ -40,10 +33,7 @@ function extractText( export const regex = ( regex: RegExp, - ): UpdateFilter< - Message | InlineQuery | ChosenInlineResult | CallbackQuery, - { match: RegExpMatchArray } - > => + ): UpdateFilter => (obj) => { const txt = extractText(obj) if (!txt) return false @@ -133,10 +123,7 @@ export const startsWith = ( return (obj) => { const txt = extractText(obj) - return ( - txt != null && - txt.toLowerCase().substring(0, str.length) === str - ) + return txt != null && txt.toLowerCase().substring(0, str.length) === str } } @@ -167,10 +154,7 @@ export const endsWith = ( return (obj) => { const txt = extractText(obj) - return ( - txt != null && - txt.toLowerCase().substring(0, str.length) === str - ) + return txt != null && txt.toLowerCase().substring(0, str.length) === str } } diff --git a/packages/dispatcher/src/filters/types.ts b/packages/dispatcher/src/filters/types.ts index db2d55fa..bef1bfbe 100644 --- a/packages/dispatcher/src/filters/types.ts +++ b/packages/dispatcher/src/filters/types.ts @@ -76,7 +76,7 @@ import { UpdateState } from '../state' // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/ban-types export type UpdateFilter = ( update: Base, - state?: UpdateState + state?: UpdateState, ) => MaybeAsync export type Modify = Omit & Mod @@ -84,27 +84,13 @@ export type Invert = { [P in keyof Mod & keyof Base]: Exclude } -export type UnionToIntersection = ( - U extends any ? (k: U) => void : never -) extends (k: infer I) => void - ? I - : never +export type UnionToIntersection = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never -export type ExtractBase = Filter extends UpdateFilter - ? I - : never +export type ExtractBase = Filter extends UpdateFilter ? I : never -export type ExtractMod = Filter extends UpdateFilter - ? I - : never +export type ExtractMod = Filter extends UpdateFilter ? I : never -export type ExtractState = Filter extends UpdateFilter< - any, - any, - infer I -> - ? I - : never +export type ExtractState = Filter extends UpdateFilter ? I : never export type TupleKeys = Exclude export type WrapBase = { @@ -112,6 +98,4 @@ export type WrapBase = { } export type Values = T[keyof T] export type UnwrapBase = T extends { base: any } ? T['base'] : never -export type ExtractBaseMany = UnwrapBase< - UnionToIntersection>> -> +export type ExtractBaseMany = UnwrapBase>>> diff --git a/packages/dispatcher/src/filters/updates.ts b/packages/dispatcher/src/filters/updates.ts index 4ba0efc7..fef3e87e 100644 --- a/packages/dispatcher/src/filters/updates.ts +++ b/packages/dispatcher/src/filters/updates.ts @@ -1,10 +1,4 @@ -import { - CallbackQuery, - ChatMemberUpdate, - ChatMemberUpdateType, - UserStatus, - UserStatusUpdate, -} from '@mtcute/client' +import { CallbackQuery, ChatMemberUpdate, ChatMemberUpdateType, UserStatus, UserStatusUpdate } from '@mtcute/client' import { MaybeArray } from '@mtcute/core' import { UpdateFilter } from './types' @@ -16,17 +10,9 @@ import { UpdateFilter } from './types' * @link ChatMemberUpdate.Type */ export const chatMember: { - (type: T): UpdateFilter< - ChatMemberUpdate, - { type: T } - > - (types: T): UpdateFilter< - ChatMemberUpdate, - { type: T[number] } - > -} = ( - types: MaybeArray, -): UpdateFilter => { + (type: T): UpdateFilter + (types: T): UpdateFilter +} = (types: MaybeArray): UpdateFilter => { if (Array.isArray(types)) { const index: Partial> = {} types.forEach((typ) => (index[typ] = true)) @@ -52,10 +38,7 @@ export const userStatus: { nextOffline: T extends 'online' ? Date : null } > - (statuses: T): UpdateFilter< - UserStatusUpdate, - { type: T[number] } - > + (statuses: T): UpdateFilter } = (statuses: MaybeArray): UpdateFilter => { if (Array.isArray(statuses)) { const index: Partial> = {} @@ -71,15 +54,10 @@ export const userStatus: { * Create a filter for {@link ChatMemberUpdate} for updates * regarding current user */ -export const chatMemberSelf: UpdateFilter< - ChatMemberUpdate, - { isSelf: true } -> = (upd) => upd.isSelf +export const chatMemberSelf: UpdateFilter = (upd) => upd.isSelf /** * Create a filter for callback queries that * originated from an inline message */ -export const callbackInline: UpdateFilter = ( - q, -) => q.isInline +export const callbackInline: UpdateFilter = (q) => q.isInline diff --git a/packages/dispatcher/src/filters/user.ts b/packages/dispatcher/src/filters/user.ts index 81e76bab..c0ded1e2 100644 --- a/packages/dispatcher/src/filters/user.ts +++ b/packages/dispatcher/src/filters/user.ts @@ -23,8 +23,7 @@ export const me: UpdateFilter = (msg) => /** * Filter messages sent by bots */ -export const bot: UpdateFilter = (msg) => - msg.sender.constructor === User && msg.sender.isBot +export const bot: UpdateFilter = (msg) => msg.sender.constructor === User && msg.sender.isBot /** * Filter updates by user ID(s) or username(s) @@ -65,11 +64,7 @@ export const userId = ( if (ctor === Message) { const sender = (upd as Message).sender - return ( - (matchSelf && sender.isSelf) || - sender.id in index || - sender.username! in index - ) + return (matchSelf && sender.isSelf) || sender.id in index || sender.username! in index } else if (ctor === UserStatusUpdate || ctor === UserTypingUpdate) { const id = (upd as UserStatusUpdate | UserTypingUpdate).userId @@ -81,28 +76,13 @@ export const userId = ( const peer = (upd as PollVoteUpdate).peer if (peer.type !== 'user') return false - return ( - (matchSelf && peer.isSelf) || - peer.id in index || - peer.username! in index - ) + return (matchSelf && peer.isSelf) || peer.id in index || peer.username! in index } - const user = ( - upd as Exclude< - typeof upd, - | Message - | UserStatusUpdate - | UserTypingUpdate - | PollVoteUpdate - > - ).user + const user = (upd as Exclude) + .user - return ( - (matchSelf && user.isSelf) || - user.id in index || - user.username! in index - ) + return (matchSelf && user.isSelf) || user.id in index || user.username! in index } } @@ -125,15 +105,8 @@ export const userId = ( return peer.isSelf } - return ( - upd as Exclude< - typeof upd, - | Message - | UserStatusUpdate - | UserTypingUpdate - | PollVoteUpdate - > - ).user.isSelf + return (upd as Exclude).user + .isSelf } } @@ -154,15 +127,8 @@ export const userId = ( } return ( - ( - upd as Exclude< - typeof upd, - | Message - | UserStatusUpdate - | UserTypingUpdate - | PollVoteUpdate - > - ).user.username === id + (upd as Exclude).user + .username === id ) } } @@ -182,15 +148,7 @@ export const userId = ( } return ( - ( - upd as Exclude< - typeof upd, - | Message - | UserStatusUpdate - | UserTypingUpdate - | PollVoteUpdate - > - ).user.id === id + (upd as Exclude).user.id === id ) } } diff --git a/packages/dispatcher/src/handler.ts b/packages/dispatcher/src/handler.ts index 785f0c70..76c9f6ea 100644 --- a/packages/dispatcher/src/handler.ts +++ b/packages/dispatcher/src/handler.ts @@ -29,11 +29,7 @@ export interface BaseUpdateHandler { check?: Checker } -export type ParsedUpdateHandler< - Name, - Update, - State = never -> = BaseUpdateHandler< +export type ParsedUpdateHandler = BaseUpdateHandler< Name, (update: Update, state: State) => MaybeAsync, (update: Update, state: State) => MaybeAsync @@ -44,73 +40,28 @@ export type RawUpdateHandler = BaseUpdateHandler< ( client: TelegramClient, update: tl.TypeUpdate | tl.TypeMessage, - peers: PeersIndex + peers: PeersIndex, ) => MaybeAsync, - ( - client: TelegramClient, - update: tl.TypeUpdate | tl.TypeMessage, - peers: PeersIndex - ) => MaybeAsync + (client: TelegramClient, update: tl.TypeUpdate | tl.TypeMessage, peers: PeersIndex) => MaybeAsync > // begin-codegen -export type NewMessageHandler = ParsedUpdateHandler< - 'new_message', - T, - S -> -export type EditMessageHandler = ParsedUpdateHandler< - 'edit_message', - T, - S -> -export type DeleteMessageHandler = ParsedUpdateHandler< - 'delete_message', - T -> -export type ChatMemberUpdateHandler = ParsedUpdateHandler< - 'chat_member', - T -> -export type InlineQueryHandler = ParsedUpdateHandler< - 'inline_query', - T -> -export type ChosenInlineResultHandler = - ParsedUpdateHandler<'chosen_inline_result', T> -export type CallbackQueryHandler< - T = CallbackQuery, - S = never -> = ParsedUpdateHandler<'callback_query', T, S> +export type NewMessageHandler = ParsedUpdateHandler<'new_message', T, S> +export type EditMessageHandler = ParsedUpdateHandler<'edit_message', T, S> +export type DeleteMessageHandler = ParsedUpdateHandler<'delete_message', T> +export type ChatMemberUpdateHandler = ParsedUpdateHandler<'chat_member', T> +export type InlineQueryHandler = ParsedUpdateHandler<'inline_query', T> +export type ChosenInlineResultHandler = ParsedUpdateHandler<'chosen_inline_result', T> +export type CallbackQueryHandler = ParsedUpdateHandler<'callback_query', T, S> export type PollUpdateHandler = ParsedUpdateHandler<'poll', T> -export type PollVoteHandler = ParsedUpdateHandler< - 'poll_vote', - T -> -export type UserStatusUpdateHandler = ParsedUpdateHandler< - 'user_status', - T -> -export type UserTypingHandler = ParsedUpdateHandler< - 'user_typing', - T -> -export type HistoryReadHandler = ParsedUpdateHandler< - 'history_read', - T -> -export type BotStoppedHandler = ParsedUpdateHandler< - 'bot_stopped', - T -> -export type BotChatJoinRequestHandler = - ParsedUpdateHandler<'bot_chat_join_request', T> -export type ChatJoinRequestHandler = - ParsedUpdateHandler<'chat_join_request', T> -export type PreCheckoutQueryHandler = ParsedUpdateHandler< - 'pre_checkout_query', - T -> +export type PollVoteHandler = ParsedUpdateHandler<'poll_vote', T> +export type UserStatusUpdateHandler = ParsedUpdateHandler<'user_status', T> +export type UserTypingHandler = ParsedUpdateHandler<'user_typing', T> +export type HistoryReadHandler = ParsedUpdateHandler<'history_read', T> +export type BotStoppedHandler = ParsedUpdateHandler<'bot_stopped', T> +export type BotChatJoinRequestHandler = ParsedUpdateHandler<'bot_chat_join_request', T> +export type ChatJoinRequestHandler = ParsedUpdateHandler<'chat_join_request', T> +export type PreCheckoutQueryHandler = ParsedUpdateHandler<'pre_checkout_query', T> export type UpdateHandler = | RawUpdateHandler diff --git a/packages/dispatcher/src/state/key.ts b/packages/dispatcher/src/state/key.ts index 2d2fb9db..3e212956 100644 --- a/packages/dispatcher/src/state/key.ts +++ b/packages/dispatcher/src/state/key.ts @@ -9,9 +9,7 @@ import { assertNever, MaybeAsync } from '@mtcute/core' * @param msg Message or callback from which to derive the key * @param scene Current scene UID, or `null` if none */ -export type StateKeyDelegate = ( - upd: Message | CallbackQuery -) => MaybeAsync +export type StateKeyDelegate = (upd: Message | CallbackQuery) => MaybeAsync /** * Default state key delegate. @@ -24,9 +22,7 @@ export type StateKeyDelegate = ( * - If in private chat (i.e. `upd.chatType === 'user'`), `upd.user.id` * - If in group/channel/supergroup (i.e. `upd.chatType !== 'user'`), `upd.chatId + '_' + upd.user.id` */ -export const defaultStateKeyDelegate: StateKeyDelegate = ( - upd, -): string | null => { +export const defaultStateKeyDelegate: StateKeyDelegate = (upd): string | null => { if (upd.constructor === Message) { switch (upd.chat.chatType) { case 'private': diff --git a/packages/dispatcher/src/state/storage.ts b/packages/dispatcher/src/state/storage.ts index de1a50c5..e76925d6 100644 --- a/packages/dispatcher/src/state/storage.ts +++ b/packages/dispatcher/src/state/storage.ts @@ -71,11 +71,7 @@ export interface IStateStorage { * @returns Tuple containing the number of remaining and * unix time in ms when the user can try again */ - getRateLimit( - key: string, - limit: number, - window: number - ): MaybeAsync<[number, number]> + getRateLimit(key: string, limit: number, window: number): MaybeAsync<[number, number]> /** * Reset a rate limit. diff --git a/packages/dispatcher/src/state/update-state.ts b/packages/dispatcher/src/state/update-state.ts index b1b59a93..f331c983 100644 --- a/packages/dispatcher/src/state/update-state.ts +++ b/packages/dispatcher/src/state/update-state.ts @@ -57,9 +57,7 @@ export class UpdateState { private _updateLocalKey(): void { if (!this._scoped) this._localKey = this._localKeyBase else { - this._localKey = this._scene ? - this._scene + '_' + this._localKeyBase : - this._localKeyBase + this._localKey = this._scene ? this._scene + '_' + this._localKeyBase : this._localKeyBase } } @@ -86,10 +84,7 @@ export class UpdateState { * @param force Whether to ignore cached state (def. `false`) */ async get(force?: boolean): Promise - async get( - fallback?: State | boolean, - force?: boolean, - ): Promise { + async get(fallback?: State | boolean, force?: boolean): Promise { if (typeof fallback === 'boolean') { force = fallback fallback = undefined @@ -101,9 +96,7 @@ export class UpdateState { return this._cached } - let res = (await this._localStorage.getState( - this._localKey, - )) as State | null + let res = (await this._localStorage.getState(this._localKey)) as State | null if (!res && fallback) res = fallback this._cached = res @@ -135,19 +128,12 @@ export class UpdateState { * @param ttl TTL for the new state (in seconds) * @param forceLoad Whether to force load the old state from storage */ - async merge( - state: Partial, - fallback?: State, - ttl?: number, - forceLoad = false, - ): Promise { + async merge(state: Partial, fallback?: State, ttl?: number, forceLoad = false): Promise { const old = await this.get(forceLoad) if (!old) { if (!fallback) { - throw new MtArgumentError( - 'Cannot use merge on empty state without fallback.', - ) + throw new MtArgumentError('Cannot use merge on empty state without fallback.') } await this.set({ ...fallback, ...state }, ttl) @@ -212,16 +198,8 @@ export class UpdateState { * @returns Tuple containing the number of remaining and * unix time in ms when the user can try again */ - async rateLimit( - key: string, - limit: number, - window: number, - ): Promise<[number, number]> { - const [remaining, reset] = await this._localStorage.getRateLimit( - `${key}:${this._localKey}`, - limit, - window, - ) + async rateLimit(key: string, limit: number, window: number): Promise<[number, number]> { + const [remaining, reset] = await this._localStorage.getRateLimit(`${key}:${this._localKey}`, limit, window) if (!remaining) { throw new RateLimitError(reset) @@ -246,11 +224,7 @@ export class UpdateState { * @returns Tuple containing the number of remaining and * unix time in ms when the user can try again */ - async throttle( - key: string, - limit: number, - window: number, - ): Promise<[number, number]> { + async throttle(key: string, limit: number, window: number): Promise<[number, number]> { try { return await this.rateLimit(key, limit, window) } catch (e: unknown) { diff --git a/packages/dispatcher/src/wizard.ts b/packages/dispatcher/src/wizard.ts index 45b8a946..eba27ac7 100644 --- a/packages/dispatcher/src/wizard.ts +++ b/packages/dispatcher/src/wizard.ts @@ -31,10 +31,10 @@ interface WizardInternalState { * that can be used to simplify implementing * step-by-step scenes. */ -export class WizardScene< - State, - SceneName extends string = string -> extends Dispatcher { +export class WizardScene extends Dispatcher< + State & WizardInternalState, + SceneName +> { private _steps = 0 private _defaultState: State & WizardInternalState = {} as State & WizardInternalState @@ -54,47 +54,36 @@ export class WizardScene< * Add a step to the wizard */ addStep( - handler: ( - msg: Message, - state: UpdateState - ) => MaybeAsync, + handler: (msg: Message, state: UpdateState) => MaybeAsync, ): void { const step = this._steps++ - const filter = filters.state( - (it) => it.$step === step, - ) + const filter = filters.state((it) => it.$step === step) - this.onNewMessage( - step === 0 ? filters.or(filters.stateEmpty, filter) : filter, - async (msg: Message, state) => { - const result = await handler(msg, state) + this.onNewMessage(step === 0 ? filters.or(filters.stateEmpty, filter) : filter, async (msg: Message, state) => { + const result = await handler(msg, state) - if (typeof result === 'number') { - await state.merge({ $step: result }, this._defaultState) + if (typeof result === 'number') { + await state.merge({ $step: result }, this._defaultState) - return - } + return + } - switch (result) { - case 'next': { - const next = step + 1 + switch (result) { + case 'next': { + const next = step + 1 - if (next === this._steps) { - await state.exit() - } else { - await state.merge( - { $step: next }, - this._defaultState, - ) - } - break - } - case 'exit': + if (next === this._steps) { await state.exit() - break + } else { + await state.merge({ $step: next }, this._defaultState) + } + break } - }, - ) + case 'exit': + await state.exit() + break + } + }) } } diff --git a/packages/dispatcher/tests/dispatcher.spec.ts b/packages/dispatcher/tests/dispatcher.spec.ts index e603e36e..af5f20ca 100644 --- a/packages/dispatcher/tests/dispatcher.spec.ts +++ b/packages/dispatcher/tests/dispatcher.spec.ts @@ -30,10 +30,7 @@ describe('Dispatcher', () => { dp.removeUpdateHandler('raw') await dp.dispatchRawUpdateNow({ _: 'updateConfig' }, emptyPeers) - expect(log).eql([ - '(first) received updateConfig', - '(second) received updateConfig', - ]) + expect(log).eql(['(first) received updateConfig', '(second) received updateConfig']) }) it('supports filters for raw updates', async () => { @@ -67,10 +64,7 @@ describe('Dispatcher', () => { await dp.dispatchRawUpdateNow({ _: 'updateConfig' }, emptyPeers) - expect(log).eql([ - '(no) received updateConfig', - '(true) received updateConfig', - ]) + expect(log).eql(['(no) received updateConfig', '(true) received updateConfig']) }) }) @@ -190,10 +184,7 @@ describe('Dispatcher', () => { await dp.dispatchRawUpdateNow({ _: 'updateConfig' }, emptyPeers) - expect(log).eql([ - '(parent) received updateConfig', - '(child) received updateConfig', - ]) + expect(log).eql(['(parent) received updateConfig', '(child) received updateConfig']) }) it('should have separate handler groups for children', async () => { diff --git a/packages/file-id/src/convert.ts b/packages/file-id/src/convert.ts index c3668dca..2effd97a 100644 --- a/packages/file-id/src/convert.ts +++ b/packages/file-id/src/convert.ts @@ -12,9 +12,7 @@ const EMPTY_BUFFER = Buffer.alloc(0) type FileId = td.RawFullRemoteFileLocation function dialogPhotoToInputPeer( - dialog: - | td.RawPhotoSizeSourceDialogPhoto - | td.RawPhotoSizeSourceDialogPhotoLegacy, + dialog: td.RawPhotoSizeSourceDialogPhoto | td.RawPhotoSizeSourceDialogPhotoLegacy, ): tl.TypeInputPeer { const markedPeerId = dialog.id const peerType = getBasicPeerType(markedPeerId) @@ -46,12 +44,12 @@ function dialogPhotoToInputPeer( * * @param fileId File ID, either parsed or as a string */ -export function fileIdToInputWebFileLocation( - fileId: string | FileId, -): tl.RawInputWebFileLocation { +export function fileIdToInputWebFileLocation(fileId: string | FileId): tl.RawInputWebFileLocation { if (typeof fileId === 'string') fileId = parseFileId(fileId) - if (fileId.location._ !== 'web') { throw new td.ConversionError('inputWebFileLocation') } + if (fileId.location._ !== 'web') { + throw new td.ConversionError('inputWebFileLocation') + } return { _: 'inputWebFileLocation', @@ -66,9 +64,7 @@ export function fileIdToInputWebFileLocation( * * @param fileId File ID, either parsed or as a string */ -export function fileIdToInputFileLocation( - fileId: string | FileId, -): tl.TypeInputFileLocation { +export function fileIdToInputFileLocation(fileId: string | FileId): tl.TypeInputFileLocation { if (typeof fileId === 'string') fileId = parseFileId(fileId) const loc = fileId.location @@ -81,9 +77,7 @@ export function fileIdToInputFileLocation( switch (loc.source._) { case 'legacy': if (!fileId.fileReference) { - throw new td.InvalidFileIdError( - 'Expected legacy photo to have file reference', - ) + throw new td.InvalidFileIdError('Expected legacy photo to have file reference') } // for some reason tdlib removed this thing altogether @@ -100,18 +94,11 @@ export function fileIdToInputFileLocation( } case 'thumbnail': if (!fileId.fileReference) { - throw new td.InvalidFileIdError( - 'Expected thumbnail photo to have file reference', - ) + throw new td.InvalidFileIdError('Expected thumbnail photo to have file reference') } - if ( - loc.source.fileType !== FileType.Photo && - loc.source.fileType !== FileType.Thumbnail - ) { - throw new td.InvalidFileIdError( - 'Expected a thumbnail to have a correct file type', - ) + if (loc.source.fileType !== FileType.Photo && loc.source.fileType !== FileType.Thumbnail) { + throw new td.InvalidFileIdError('Expected a thumbnail to have a correct file type') } return { @@ -146,9 +133,7 @@ export function fileIdToInputFileLocation( } case 'fullLegacy': if (!fileId.fileReference) { - throw new td.InvalidFileIdError( - 'Expected legacy photo to have file reference', - ) + throw new td.InvalidFileIdError('Expected legacy photo to have file reference') } return { @@ -197,9 +182,7 @@ export function fileIdToInputFileLocation( } case 'common': { if (!fileId.fileReference) { - throw new td.InvalidFileIdError( - 'Expected common to have file reference', - ) + throw new td.InvalidFileIdError('Expected common to have file reference') } if (fileId.type === FileType.Encrypted) { @@ -208,10 +191,7 @@ export function fileIdToInputFileLocation( id: loc.id, accessHash: loc.accessHash, } - } else if ( - fileId.type === FileType.Secure || - fileId.type === FileType.SecureRaw - ) { + } else if (fileId.type === FileType.Secure || fileId.type === FileType.SecureRaw) { return { _: 'inputSecureFileLocation', id: loc.id, @@ -238,9 +218,7 @@ export function fileIdToInputFileLocation( * * @param fileId File ID, either parsed or as a string */ -export function fileIdToInputDocument( - fileId: string | FileId, -): tl.RawInputDocument { +export function fileIdToInputDocument(fileId: string | FileId): tl.RawInputDocument { if (typeof fileId === 'string') fileId = parseFileId(fileId) if ( @@ -248,7 +226,9 @@ export function fileIdToInputDocument( fileId.type === FileType.Secure || fileId.type === FileType.SecureRaw || fileId.type === FileType.Encrypted - ) { throw new td.ConversionError('inputDocument') } + ) { + throw new td.ConversionError('inputDocument') + } let fileRef = fileId.fileReference @@ -257,9 +237,7 @@ export function fileIdToInputDocument( // older stickers' file IDs don't have file ref fileRef = EMPTY_BUFFER } else { - throw new td.InvalidFileIdError( - 'Expected document to have file reference', - ) + throw new td.InvalidFileIdError('Expected document to have file reference') } } @@ -280,9 +258,13 @@ export function fileIdToInputDocument( export function fileIdToInputPhoto(fileId: string | FileId): tl.RawInputPhoto { if (typeof fileId === 'string') fileId = parseFileId(fileId) - if (fileId.location._ !== 'photo') { throw new td.ConversionError('inputPhoto') } + if (fileId.location._ !== 'photo') { + throw new td.ConversionError('inputPhoto') + } - if (!fileId.fileReference) { throw new td.InvalidFileIdError('Expected photo to have file reference') } + if (!fileId.fileReference) { + throw new td.InvalidFileIdError('Expected photo to have file reference') + } return { _: 'inputPhoto', @@ -298,12 +280,12 @@ export function fileIdToInputPhoto(fileId: string | FileId): tl.RawInputPhoto { * * @param fileId File ID, either parsed or as a string */ -export function fileIdToEncryptedFile( - fileId: string | FileId, -): tl.RawInputEncryptedFile { +export function fileIdToEncryptedFile(fileId: string | FileId): tl.RawInputEncryptedFile { if (typeof fileId === 'string') fileId = parseFileId(fileId) - if (fileId.location._ !== 'common' || fileId.type !== FileType.Encrypted) { throw new td.ConversionError('inputEncryptedFile') } + if (fileId.location._ !== 'common' || fileId.type !== FileType.Encrypted) { + throw new td.ConversionError('inputEncryptedFile') + } return { _: 'inputEncryptedFile', @@ -318,15 +300,12 @@ export function fileIdToEncryptedFile( * * @param fileId File ID, either parsed or as a string */ -export function fileIdToSecureFile( - fileId: string | FileId, -): tl.RawInputSecureFile { +export function fileIdToSecureFile(fileId: string | FileId): tl.RawInputSecureFile { if (typeof fileId === 'string') fileId = parseFileId(fileId) - if ( - fileId.location._ !== 'common' || - (fileId.type !== FileType.Secure && fileId.type !== FileType.SecureRaw) - ) { throw new td.ConversionError('inputSecureFile') } + if (fileId.location._ !== 'common' || (fileId.type !== FileType.Secure && fileId.type !== FileType.SecureRaw)) { + throw new td.ConversionError('inputSecureFile') + } return { _: 'inputSecureFile', diff --git a/packages/file-id/src/parse.ts b/packages/file-id/src/parse.ts index 5c34ab99..f935df42 100644 --- a/packages/file-id/src/parse.ts +++ b/packages/file-id/src/parse.ts @@ -4,9 +4,7 @@ import { TlBinaryReader } from '@mtcute/tl-runtime' import { tdFileId as td } from './types' import { telegramRleDecode } from './utils' -function parseWebFileLocation( - reader: TlBinaryReader, -): td.RawWebRemoteFileLocation { +function parseWebFileLocation(reader: TlBinaryReader): td.RawWebRemoteFileLocation { return { _: 'web', url: reader.string(), @@ -27,20 +25,14 @@ function parsePhotoSizeSource(reader: TlBinaryReader): td.TypePhotoSizeSource { const fileType = reader.int() if (fileType < 0 || fileType >= td.FileType.Size) { - throw new td.UnsupportedError( - `Unsupported file type: ${fileType} (${reader.data.toString( - 'base64', - )})`, - ) + throw new td.UnsupportedError(`Unsupported file type: ${fileType} (${reader.data.toString('base64')})`) } const thumbnailType = reader.int() if (thumbnailType < 0 || thumbnailType > 255) { throw new td.InvalidFileIdError( - `Wrong thumbnail type: ${thumbnailType} (${reader.data.toString( - 'base64', - )})`, + `Wrong thumbnail type: ${thumbnailType} (${reader.data.toString('base64')})`, ) } @@ -119,17 +111,12 @@ function parsePhotoSizeSource(reader: TlBinaryReader): td.TypePhotoSizeSource { } default: throw new td.UnsupportedError( - `Unsupported photo size source ${variant} (${reader.data.toString( - 'base64', - )})`, + `Unsupported photo size source ${variant} (${reader.data.toString('base64')})`, ) } } -function parsePhotoFileLocation( - reader: TlBinaryReader, - version: number, -): td.RawPhotoRemoteFileLocation { +function parsePhotoFileLocation(reader: TlBinaryReader, version: number): td.RawPhotoRemoteFileLocation { const id = reader.long() const accessHash = reader.long() let source: td.TypePhotoSizeSource @@ -184,9 +171,7 @@ function parsePhotoFileLocation( } break default: - throw new td.InvalidFileIdError( - 'Invalid PhotoSizeSource in legacy PhotoRemoteFileLocation', - ) + throw new td.InvalidFileIdError('Invalid PhotoSizeSource in legacy PhotoRemoteFileLocation') } } @@ -198,9 +183,7 @@ function parsePhotoFileLocation( } } -function parseCommonFileLocation( - reader: TlBinaryReader, -): td.RawCommonRemoteFileLocation { +function parseCommonFileLocation(reader: TlBinaryReader): td.RawCommonRemoteFileLocation { return { _: 'common', id: reader.long(), @@ -208,16 +191,9 @@ function parseCommonFileLocation( } } -function fromPersistentIdV23( - binary: Buffer, - version: number, -): td.RawFullRemoteFileLocation { +function fromPersistentIdV23(binary: Buffer, version: number): td.RawFullRemoteFileLocation { if (version < 0 || version > td.CURRENT_VERSION) { - throw new td.UnsupportedError( - `Unsupported file ID v3 subversion: ${version} (${binary.toString( - 'base64', - )})`, - ) + throw new td.UnsupportedError(`Unsupported file ID v3 subversion: ${version} (${binary.toString('base64')})`) } binary = telegramRleDecode(binary) @@ -233,9 +209,7 @@ function fromPersistentIdV23( fileType &= ~td.FILE_REFERENCE_FLAG if (fileType < 0 || fileType >= td.FileType.Size) { - throw new td.UnsupportedError( - `Unsupported file type: ${fileType} (${binary.toString('base64')})`, - ) + throw new td.UnsupportedError(`Unsupported file type: ${fileType} (${binary.toString('base64')})`) } const dcId = reader.int() @@ -275,17 +249,13 @@ function fromPersistentIdV23( fileType !== td.FileType.Thumbnail && fileType !== td.FileType.EncryptedThumbnail) ) { - throw new td.InvalidFileIdError( - 'Invalid FileType in PhotoRemoteFileLocation Thumbnail', - ) + throw new td.InvalidFileIdError('Invalid FileType in PhotoRemoteFileLocation Thumbnail') } break case 'dialogPhoto': case 'dialogPhotoLegacy': if (fileType !== td.FileType.ProfilePhoto) { - throw new td.InvalidFileIdError( - 'Invalid FileType in PhotoRemoteFileLocation DialogPhoto', - ) + throw new td.InvalidFileIdError('Invalid FileType in PhotoRemoteFileLocation DialogPhoto') } break case 'stickerSetThumbnail': @@ -318,11 +288,7 @@ function fromPersistentIdV23( break } default: - throw new td.UnsupportedError( - `Invalid file type: ${fileType} (${binary.toString( - 'base64', - )})`, - ) + throw new td.UnsupportedError(`Invalid file type: ${fileType} (${binary.toString('base64')})`) } } @@ -350,9 +316,7 @@ function fromPersistentIdV3(binary: Buffer) { * * @param fileId File ID as a base-64 encoded string or Buffer */ -export function parseFileId( - fileId: string | Buffer, -): td.RawFullRemoteFileLocation { +export function parseFileId(fileId: string | Buffer): td.RawFullRemoteFileLocation { if (typeof fileId === 'string') fileId = parseUrlSafeBase64(fileId) const version = fileId[fileId.length - 1] @@ -365,7 +329,5 @@ export function parseFileId( return fromPersistentIdV3(fileId) } - throw new td.UnsupportedError( - `Unsupported file ID version: ${version} (${fileId.toString('base64')})`, - ) + throw new td.UnsupportedError(`Unsupported file ID version: ${version} (${fileId.toString('base64')})`) } diff --git a/packages/file-id/src/serialize-unique.ts b/packages/file-id/src/serialize-unique.ts index 9e4b5de9..d4985dd4 100644 --- a/packages/file-id/src/serialize-unique.ts +++ b/packages/file-id/src/serialize-unique.ts @@ -22,13 +22,8 @@ export type InputUniqueLocation = * * @param location Information about file location */ -export function toUniqueFileId( - location: Omit -): string -export function toUniqueFileId( - type: td.FileType, - location: InputUniqueLocation -): string +export function toUniqueFileId(location: Omit): string +export function toUniqueFileId(type: td.FileType, location: InputUniqueLocation): string export function toUniqueFileId( first: td.FileType | Omit, @@ -74,9 +69,7 @@ export function toUniqueFileId( type = 5 break default: - throw new td.InvalidFileIdError( - `Invalid file type: ${inputType}`, - ) + throw new td.InvalidFileIdError(`Invalid file type: ${inputType}`) } } @@ -149,10 +142,7 @@ export function toUniqueFileId( break } case 'web': - writer = TlBinaryWriter.alloc( - undefined, - Buffer.byteLength(inputLocation.url, 'utf-8') + 8, - ) + writer = TlBinaryWriter.alloc(undefined, Buffer.byteLength(inputLocation.url, 'utf-8') + 8) writer.int(type) writer.string(inputLocation.url) break diff --git a/packages/file-id/src/serialize.ts b/packages/file-id/src/serialize.ts index 58a1ea7b..6079cf2f 100644 --- a/packages/file-id/src/serialize.ts +++ b/packages/file-id/src/serialize.ts @@ -13,9 +13,7 @@ const SUFFIX = Buffer.from([td.CURRENT_VERSION, td.PERSISTENT_ID_VERSION]) * * @param location Information about file location */ -export function toFileId( - location: Omit, -): string { +export function toFileId(location: Omit): string { const loc = location.location let type: number = location.type @@ -29,10 +27,7 @@ export function toFileId( // // longest file ids are around 80 bytes, so i guess // we are safe with allocating 100 bytes - const writer = TlBinaryWriter.alloc( - undefined, - loc._ === 'web' ? Buffer.byteLength(loc.url, 'utf8') + 32 : 100, - ) + const writer = TlBinaryWriter.alloc(undefined, loc._ === 'web' ? Buffer.byteLength(loc.url, 'utf8') + 32 : 100) writer.int(type) writer.int(location.dcId) @@ -110,7 +105,5 @@ export function toFileId( assertNever(loc) } - return encodeUrlSafeBase64( - Buffer.concat([telegramRleEncode(writer.result()), SUFFIX]), - ) + return encodeUrlSafeBase64(Buffer.concat([telegramRleEncode(writer.result()), SUFFIX])) } diff --git a/packages/file-id/src/types.ts b/packages/file-id/src/types.ts index 3383fd5e..17b83fac 100644 --- a/packages/file-id/src/types.ts +++ b/packages/file-id/src/types.ts @@ -127,8 +127,7 @@ export namespace tdFileId { /** * This photo is a legacy dialog photo */ - export interface RawPhotoSizeSourceDialogPhotoLegacy - extends Omit { + export interface RawPhotoSizeSourceDialogPhotoLegacy extends Omit { readonly _: 'dialogPhotoLegacy' readonly volumeId: Long readonly localId: number @@ -232,9 +231,7 @@ export namespace tdFileId { readonly location: TypeRemoteFileLocation } - export function isFileIdLike( - obj: unknown, - ): obj is string | RawFullRemoteFileLocation { + export function isFileIdLike(obj: unknown): obj is string | RawFullRemoteFileLocation { return ( typeof obj === 'string' || (obj !== null && typeof obj === 'object' && (obj as { _: unknown })._ === 'remoteFileLocation') diff --git a/packages/file-id/tests/parse.spec.ts b/packages/file-id/tests/parse.spec.ts index c44fdd85..0bf93c46 100644 --- a/packages/file-id/tests/parse.spec.ts +++ b/packages/file-id/tests/parse.spec.ts @@ -13,65 +13,47 @@ describe('parsing file ids', () => { } it('parses common file ids', () => { - test( - 'CAACAgIAAxkBAAEJny9gituz1_V_uSKBUuG_nhtzEtFOeQACXFoAAuCjggfYjw_KAAGSnkgfBA', - { - _: 'remoteFileLocation', - dcId: 2, - fileReference: Buffer.from( - '0100099f2f608adbb3d7f57fb9228152e1bf9e1b7312d14e79', - 'hex', - ), - location: { - _: 'common', - accessHash: Long.fromString('5232780349138767832'), - id: Long.fromString('541175087705905756'), - }, - type: td.FileType.Sticker, + test('CAACAgIAAxkBAAEJny9gituz1_V_uSKBUuG_nhtzEtFOeQACXFoAAuCjggfYjw_KAAGSnkgfBA', { + _: 'remoteFileLocation', + dcId: 2, + fileReference: Buffer.from('0100099f2f608adbb3d7f57fb9228152e1bf9e1b7312d14e79', 'hex'), + location: { + _: 'common', + accessHash: Long.fromString('5232780349138767832'), + id: Long.fromString('541175087705905756'), }, - ) - test( - 'BQACAgIAAxkBAAEJnzNgit00IDsKd07OdSeanwz8osecYAACdAwAAueoWEicaPvNdOYEwB8E', - { - _: 'remoteFileLocation', - dcId: 2, - fileReference: Buffer.from( - '0100099f33608add34203b0a774ece75279a9f0cfca2c79c60', - 'hex', - ), - location: { - _: 'common', - accessHash: Long.fromString('-4610306729174144868'), - id: Long.fromString('5213102278772264052'), - }, - type: td.FileType.Document, + type: td.FileType.Sticker, + }) + test('BQACAgIAAxkBAAEJnzNgit00IDsKd07OdSeanwz8osecYAACdAwAAueoWEicaPvNdOYEwB8E', { + _: 'remoteFileLocation', + dcId: 2, + fileReference: Buffer.from('0100099f33608add34203b0a774ece75279a9f0cfca2c79c60', 'hex'), + location: { + _: 'common', + accessHash: Long.fromString('-4610306729174144868'), + id: Long.fromString('5213102278772264052'), }, - ) + type: td.FileType.Document, + }) }) it('parses thumbnails file ids', () => { - test( - 'AAMCAgADGQEAAQmfL2CK27PX9X-5IoFS4b-eG3MS0U55AAJcWgAC4KOCB9iPD8oAAZKeSK1c8w4ABAEAB20AA1kCAAIfBA', - { - _: 'remoteFileLocation', - dcId: 2, - fileReference: Buffer.from( - '0100099f2f608adbb3d7f57fb9228152e1bf9e1b7312d14e79', - 'hex', - ), - location: { - _: 'photo', - accessHash: Long.fromString('5232780349138767832'), - id: Long.fromString('541175087705905756'), - source: { - _: 'thumbnail', - fileType: td.FileType.Thumbnail, - thumbnailType: 'm', - }, + test('AAMCAgADGQEAAQmfL2CK27PX9X-5IoFS4b-eG3MS0U55AAJcWgAC4KOCB9iPD8oAAZKeSK1c8w4ABAEAB20AA1kCAAIfBA', { + _: 'remoteFileLocation', + dcId: 2, + fileReference: Buffer.from('0100099f2f608adbb3d7f57fb9228152e1bf9e1b7312d14e79', 'hex'), + location: { + _: 'photo', + accessHash: Long.fromString('5232780349138767832'), + id: Long.fromString('541175087705905756'), + source: { + _: 'thumbnail', + fileType: td.FileType.Thumbnail, + thumbnailType: 'm', }, - type: td.FileType.Thumbnail, }, - ) + type: td.FileType.Thumbnail, + }) }) it('parses profile pictures', () => { diff --git a/packages/file-id/tests/serialize-unique.spec.ts b/packages/file-id/tests/serialize-unique.spec.ts index d1cd02ff..45a7dac3 100644 --- a/packages/file-id/tests/serialize-unique.spec.ts +++ b/packages/file-id/tests/serialize-unique.spec.ts @@ -15,34 +15,19 @@ describe('serializing unique file ids', () => { }) it('serializes unique ids for common file ids', () => { - test( - 'CAACAgEAAx0CVgtngQACAuFfU1GY9wiRG7A7jlIBbP2yvAostAACegAD997LEUiQZafDlhIeGwQ', - 'AgADegAD997LEQ', - ) - test( - 'BQACAgIAAxkBAAEJnzNgit00IDsKd07OdSeanwz8osecYAACdAwAAueoWEicaPvNdOYEwB8E', - 'AgADdAwAAueoWEg', - ) + test('CAACAgEAAx0CVgtngQACAuFfU1GY9wiRG7A7jlIBbP2yvAostAACegAD997LEUiQZafDlhIeGwQ', 'AgADegAD997LEQ') + test('BQACAgIAAxkBAAEJnzNgit00IDsKd07OdSeanwz8osecYAACdAwAAueoWEicaPvNdOYEwB8E', 'AgADdAwAAueoWEg') test( 'AAMCAgADGQEAAQmfM2CK3TQgOwp3Ts51J5qfDPyix5xgAAJ0DAAC56hYSJxo-8105gTAT_bYoy4AAwEAB20AA0JBAAIfBA', 'AQADdAwAAueoWEhy', ) - test( - 'CAACAgIAAxkBAAEJny9gituz1_V_uSKBUuG_nhtzEtFOeQACXFoAAuCjggfYjw_KAAGSnkgfBA', - 'AgADXFoAAuCjggc', - ) + test('CAACAgIAAxkBAAEJny9gituz1_V_uSKBUuG_nhtzEtFOeQACXFoAAuCjggfYjw_KAAGSnkgfBA', 'AgADXFoAAuCjggc') }) it('serializes unique ids for profile pictures', () => { // big - test( - 'AQADAgATySHBDgAEAwAD0npI3Bb___-wfxjpg7QCPf8pBQABHwQ', - 'AQADySHBDgAE_ykFAAE', - ) + test('AQADAgATySHBDgAEAwAD0npI3Bb___-wfxjpg7QCPf8pBQABHwQ', 'AQADySHBDgAE_ykFAAE') // small - test( - 'AQADAgATySHBDgAEAgAD0npI3Bb___-wfxjpg7QCPf0pBQABHwQ', - 'AQADySHBDgAE_SkFAAE', - ) + test('AQADAgATySHBDgAEAgAD0npI3Bb___-wfxjpg7QCPf0pBQABHwQ', 'AQADySHBDgAE_SkFAAE') }) }) diff --git a/packages/file-id/tests/utils.spec.ts b/packages/file-id/tests/utils.spec.ts index 773d1ba7..3056a16c 100644 --- a/packages/file-id/tests/utils.spec.ts +++ b/packages/file-id/tests/utils.spec.ts @@ -5,55 +5,27 @@ import { telegramRleDecode, telegramRleEncode } from '../src/utils' describe('telegramRleEncode', () => { it('should not modify input if there are no \\x00', () => { - expect( - telegramRleEncode(Buffer.from('aaeeff', 'hex')).toString('hex'), - ).eq('aaeeff') + expect(telegramRleEncode(Buffer.from('aaeeff', 'hex')).toString('hex')).eq('aaeeff') }) it('should collapse consecutive \\x00', () => { - expect( - telegramRleEncode(Buffer.from('00000000aa', 'hex')).toString('hex'), - ).eq('0004aa') - expect( - telegramRleEncode( - Buffer.from('00000000aa000000aa', 'hex'), - ).toString('hex'), - ).eq('0004aa0003aa') - expect( - telegramRleEncode(Buffer.from('00000000aa0000', 'hex')).toString( - 'hex', - ), - ).eq('0004aa0002') - expect( - telegramRleEncode(Buffer.from('00aa00', 'hex')).toString('hex'), - ).eq('0001aa0001') + expect(telegramRleEncode(Buffer.from('00000000aa', 'hex')).toString('hex')).eq('0004aa') + expect(telegramRleEncode(Buffer.from('00000000aa000000aa', 'hex')).toString('hex')).eq('0004aa0003aa') + expect(telegramRleEncode(Buffer.from('00000000aa0000', 'hex')).toString('hex')).eq('0004aa0002') + expect(telegramRleEncode(Buffer.from('00aa00', 'hex')).toString('hex')).eq('0001aa0001') }) }) describe('telegramRleDecode', () => { it('should not mofify input if there are no \\x00', () => { - expect( - telegramRleDecode(Buffer.from('aaeeff', 'hex')).toString('hex'), - ).eq('aaeeff') + expect(telegramRleDecode(Buffer.from('aaeeff', 'hex')).toString('hex')).eq('aaeeff') }) it('should expand two-byte sequences starting with \\x00', () => { - expect( - telegramRleDecode(Buffer.from('0004aa', 'hex')).toString('hex'), - ).eq('00000000aa') - expect( - telegramRleDecode(Buffer.from('0004aa0000', 'hex')).toString('hex'), - ).eq('00000000aa') - expect( - telegramRleDecode(Buffer.from('0004aa0003aa', 'hex')).toString( - 'hex', - ), - ).eq('00000000aa000000aa') - expect( - telegramRleDecode(Buffer.from('0004aa0002', 'hex')).toString('hex'), - ).eq('00000000aa0000') - expect( - telegramRleDecode(Buffer.from('0001aa0001', 'hex')).toString('hex'), - ).eq('00aa00') + expect(telegramRleDecode(Buffer.from('0004aa', 'hex')).toString('hex')).eq('00000000aa') + expect(telegramRleDecode(Buffer.from('0004aa0000', 'hex')).toString('hex')).eq('00000000aa') + expect(telegramRleDecode(Buffer.from('0004aa0003aa', 'hex')).toString('hex')).eq('00000000aa000000aa') + expect(telegramRleDecode(Buffer.from('0004aa0002', 'hex')).toString('hex')).eq('00000000aa0000') + expect(telegramRleDecode(Buffer.from('0001aa0001', 'hex')).toString('hex')).eq('00aa00') }) }) diff --git a/packages/html-parser/src/index.ts b/packages/html-parser/src/index.ts index 28f2fea7..b8b3a808 100644 --- a/packages/html-parser/src/index.ts +++ b/packages/html-parser/src/index.ts @@ -1,15 +1,9 @@ import { Parser } from 'htmlparser2' import Long from 'long' -import type { - FormattedString, - IMessageEntityParser, - MessageEntity, - tl, -} from '@mtcute/client' +import type { FormattedString, IMessageEntityParser, MessageEntity, tl } from '@mtcute/client' -const MENTION_REGEX = - /^tg:\/\/user\?id=(\d+)(?:&hash=(-?[0-9a-fA-F]+)(?:&|$)|&|$)/ +const MENTION_REGEX = /^tg:\/\/user\?id=(\d+)(?:&hash=(-?[0-9a-fA-F]+)(?:&|$)|&|$)/ /** * Tagged template based helper for escaping entities in HTML @@ -28,10 +22,7 @@ export function html( if (typeof it === 'boolean' || !it) return if (typeof it === 'string') { - it = HtmlMessageEntityParser.escape( - it, - Boolean(str.match(/=['"]$/)), - ) + it = HtmlMessageEntityParser.escape(it, Boolean(str.match(/=['"]$/))) } else { if (it.mode && it.mode !== 'html') { throw new Error(`Incompatible parse mode: ${it.mode}`) @@ -79,10 +70,7 @@ export class HtmlMessageEntityParser implements IMessageEntityParser { * @param quote Whether `"` (double quote) should be escaped as `"` */ static escape(str: string, quote = false): string { - str = str - .replace(/&/g, '&') - .replace(//g, '>') + str = str.replace(/&/g, '&').replace(//g, '>') if (quote) str = str.replace(/"/g, '"') return str @@ -227,11 +215,7 @@ export class HtmlMessageEntityParser implements IMessageEntityParser { userId: { _: 'inputUser', userId: id, - accessHash: Long.fromString( - accessHash, - false, - 16, - ), + accessHash: Long.fromString(accessHash, false, 16), }, } } else { @@ -335,11 +319,7 @@ export class HtmlMessageEntityParser implements IMessageEntityParser { if (relativeOffset > lastOffset) { // add missing plain text - html.push( - HtmlMessageEntityParser.escape( - text.substring(lastOffset, relativeOffset), - ), - ) + html.push(HtmlMessageEntityParser.escape(text.substring(lastOffset, relativeOffset))) } else if (relativeOffset < lastOffset) { length -= lastOffset - relativeOffset relativeOffset = lastOffset @@ -361,13 +341,7 @@ export class HtmlMessageEntityParser implements IMessageEntityParser { if (type === 'pre') { entityText = substr } else { - entityText = this._unparse( - substr, - entities, - i + 1, - offset + relativeOffset, - length, - ) + entityText = this._unparse(substr, entities, i + 1, offset + relativeOffset, length) } switch (type) { @@ -380,16 +354,9 @@ export class HtmlMessageEntityParser implements IMessageEntityParser { case 'code': case 'pre': html.push( - `<${type}${ - entity.language ? - ` language="${entity.language}"` : - '' - }>${ + `<${type}${entity.language ? ` language="${entity.language}"` : ''}>${ this._syntaxHighlighter && entity.language ? - this._syntaxHighlighter( - entityText, - entity.language, - ) : + this._syntaxHighlighter(entityText, entity.language) : entityText }`, ) @@ -399,9 +366,7 @@ export class HtmlMessageEntityParser implements IMessageEntityParser { html.push(`<${type}>${entityText}`) break case 'email': - html.push( - `${entityText}`, - ) + html.push(`${entityText}`) break case 'url': html.push(`${entityText}`) diff --git a/packages/html-parser/tests/html-parser.spec.ts b/packages/html-parser/tests/html-parser.spec.ts index 05635fb0..8a31d51c 100644 --- a/packages/html-parser/tests/html-parser.spec.ts +++ b/packages/html-parser/tests/html-parser.spec.ts @@ -11,10 +11,7 @@ const createEntity = ( type: T, offset: number, length: number, - additional?: Omit< - tl.FindByName, - '_' | 'offset' | 'length' - >, + additional?: Omit, '_' | 'offset' | 'length'>, ): tl.TypeMessageEntity => { return { _: type, @@ -25,21 +22,14 @@ const createEntity = ( } const createEntities = (entities: tl.TypeMessageEntity[]): MessageEntity[] => { - return entities - .map((it) => MessageEntity._parse(it)) - .filter((it) => it !== null) as MessageEntity[] + return entities.map((it) => MessageEntity._parse(it)).filter((it) => it !== null) as MessageEntity[] } describe('HtmlMessageEntityParser', () => { const parser = new HtmlMessageEntityParser() describe('unparse', () => { - const test = ( - text: string, - entities: tl.TypeMessageEntity[], - expected: string, - _parser = parser, - ): void => { + const test = (text: string, entities: tl.TypeMessageEntity[], expected: string, _parser = parser): void => { expect(_parser.unparse(text, createEntities(entities))).eq(expected) } @@ -108,10 +98,7 @@ describe('HtmlMessageEntityParser', () => { it('should support entities on the edges', () => { test( 'Hello, world', - [ - createEntity('messageEntityBold', 0, 5), - createEntity('messageEntityBold', 7, 5), - ], + [createEntity('messageEntityBold', 0, 5), createEntity('messageEntityBold', 7, 5)], 'Hello, world', ) }) @@ -119,29 +106,19 @@ describe('HtmlMessageEntityParser', () => { it('should clamp out-of-range entities', () => { test( 'Hello, world', - [ - createEntity('messageEntityBold', -2, 7), - createEntity('messageEntityBold', 7, 10), - ], + [createEntity('messageEntityBold', -2, 7), createEntity('messageEntityBold', 7, 10)], 'Hello, world', ) }) it('should ignore entities outside the length', () => { - test( - 'Hello, world', - [createEntity('messageEntityBold', 50, 5)], - 'Hello, world', - ) + test('Hello, world', [createEntity('messageEntityBold', 50, 5)], 'Hello, world') }) it('should support entities followed by each other', () => { test( 'plain Hello, world plain', - [ - createEntity('messageEntityBold', 6, 6), - createEntity('messageEntityItalic', 12, 6), - ], + [createEntity('messageEntityBold', 6, 6), createEntity('messageEntityItalic', 12, 6)], 'plain Hello, world plain', ) }) @@ -149,10 +126,7 @@ describe('HtmlMessageEntityParser', () => { it('should support nested entities', () => { test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityItalic', 0, 24), - createEntity('messageEntityBold', 15, 8), - ], + [createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 15, 8)], 'Welcome to the gym zone!', ) }) @@ -160,34 +134,22 @@ describe('HtmlMessageEntityParser', () => { it('should support nested entities with the same edges', () => { test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityItalic', 0, 24), - createEntity('messageEntityBold', 15, 9), - ], + [createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 15, 9)], 'Welcome to the gym zone!', ) test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityBold', 0, 24), - createEntity('messageEntityItalic', 15, 9), - ], + [createEntity('messageEntityBold', 0, 24), createEntity('messageEntityItalic', 15, 9)], 'Welcome to the gym zone!', ) test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityItalic', 0, 24), - createEntity('messageEntityBold', 0, 7), - ], + [createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 0, 7)], 'Welcome to the gym zone!', ) test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityItalic', 0, 24), - createEntity('messageEntityBold', 0, 24), - ], + [createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 0, 24)], 'Welcome to the gym zone!', ) }) @@ -195,10 +157,7 @@ describe('HtmlMessageEntityParser', () => { it('should support overlapping entities', () => { test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityItalic', 0, 14), - createEntity('messageEntityBold', 8, 10), - ], + [createEntity('messageEntityItalic', 0, 14), createEntity('messageEntityBold', 8, 10)], 'Welcome to the gym zone!', ) test( @@ -244,8 +203,7 @@ describe('HtmlMessageEntityParser', () => { it('should work with custom syntax highlighter', () => { const parser = new HtmlMessageEntityParser({ - syntaxHighlighter: (code, lang) => - `lang: ${lang}
${code}`, + syntaxHighlighter: (code, lang) => `lang: ${lang}
${code}`, }) test( @@ -263,16 +221,8 @@ describe('HtmlMessageEntityParser', () => { it('should replace newlines with
outside pre', () => { test('plain\n\nplain', [], 'plain

plain') - test( - 'plain\n\nplain', - [createEntity('messageEntityBold', 0, 12)], - 'plain

plain
', - ) - test( - 'plain\n\nplain', - [createEntity('messageEntityPre', 0, 12)], - '
plain\n\nplain
', - ) + test('plain\n\nplain', [createEntity('messageEntityBold', 0, 12)], 'plain

plain
') + test('plain\n\nplain', [createEntity('messageEntityPre', 0, 12)], '
plain\n\nplain
') }) it('should replace multiple spaces with  ', () => { @@ -281,11 +231,7 @@ describe('HtmlMessageEntityParser', () => { }) describe('parse', () => { - const test = ( - text: string, - expectedEntities: tl.TypeMessageEntity[], - expectedText: string, - ): void => { + const test = (text: string, expectedEntities: tl.TypeMessageEntity[], expectedText: string): void => { const [_text, entities] = parser.parse(text) expect(_text).eql(expectedText) expect(entities).eql(expectedEntities) @@ -373,11 +319,7 @@ describe('HtmlMessageEntityParser', () => { }) it('should ignore newlines and indentation', () => { - test( - 'this is some text\n\nwith newlines', - [], - 'this is some text with newlines', - ) + test('this is some text\n\nwith newlines', [], 'this is some text with newlines') test( 'this is some text\n\nwith newlines', [createEntity('messageEntityBold', 0, 22)], @@ -397,10 +339,7 @@ describe('HtmlMessageEntityParser', () => { yeah so cool `, - [ - createEntity('messageEntityBold', 45, 13), - createEntity('messageEntityItalic', 64, 7), - ], + [createEntity('messageEntityBold', 45, 13), createEntity('messageEntityItalic', 64, 7)], 'this is some indented text with newlines and indented tags yeah so cool', ) }) @@ -442,11 +381,7 @@ describe('HtmlMessageEntityParser', () => { }) it('should handle
', () => { - test( - 'this is some text

with actual newlines', - [], - 'this is some text\n\nwith actual newlines', - ) + test('this is some text

with actual newlines', [], 'this is some text\n\nwith actual newlines') test( 'this is some text

with actual newlines', // note that the
(i.e. \n) is not included in the entity @@ -467,10 +402,7 @@ describe('HtmlMessageEntityParser', () => { it('should support entities on the edges', () => { test( 'Hello, world', - [ - createEntity('messageEntityBold', 0, 5), - createEntity('messageEntityBold', 7, 5), - ], + [createEntity('messageEntityBold', 0, 5), createEntity('messageEntityBold', 7, 5)], 'Hello, world', ) }) @@ -482,10 +414,7 @@ describe('HtmlMessageEntityParser', () => { it('should support entities followed by each other', () => { test( 'plain Hello, world plain', - [ - createEntity('messageEntityBold', 6, 6), - createEntity('messageEntityItalic', 12, 6), - ], + [createEntity('messageEntityBold', 6, 6), createEntity('messageEntityItalic', 12, 6)], 'plain Hello, world plain', ) }) @@ -493,10 +422,7 @@ describe('HtmlMessageEntityParser', () => { it('should support nested entities', () => { test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityBold', 15, 8), - createEntity('messageEntityItalic', 0, 24), - ], + [createEntity('messageEntityBold', 15, 8), createEntity('messageEntityItalic', 0, 24)], 'Welcome to the gym zone!', ) }) @@ -504,34 +430,22 @@ describe('HtmlMessageEntityParser', () => { it('should support nested entities with the same edges', () => { test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityBold', 15, 9), - createEntity('messageEntityItalic', 0, 24), - ], + [createEntity('messageEntityBold', 15, 9), createEntity('messageEntityItalic', 0, 24)], 'Welcome to the gym zone!', ) test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityItalic', 15, 9), - createEntity('messageEntityBold', 0, 24), - ], + [createEntity('messageEntityItalic', 15, 9), createEntity('messageEntityBold', 0, 24)], 'Welcome to the gym zone!', ) test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityBold', 0, 7), - createEntity('messageEntityItalic', 0, 24), - ], + [createEntity('messageEntityBold', 0, 7), createEntity('messageEntityItalic', 0, 24)], 'Welcome to the gym zone!', ) test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityBold', 0, 24), - createEntity('messageEntityItalic', 0, 24), - ], + [createEntity('messageEntityBold', 0, 24), createEntity('messageEntityItalic', 0, 24)], 'Welcome to the gym zone!', ) }) @@ -549,11 +463,7 @@ describe('HtmlMessageEntityParser', () => { }) it('should handle non-escaped special symbols', () => { - test( - '<&> < & > <&>', - [createEntity('messageEntityBold', 4, 5)], - '<&> < & > <&>', - ) + test('<&> < & > <&>', [createEntity('messageEntityBold', 4, 5)], '<&> < & > <&>') }) it('should unescape special symbols', () => { @@ -583,15 +493,9 @@ describe('HtmlMessageEntityParser', () => { const unsafeString = '<&>' expect(html`${unsafeString}`.value).eq('<&>') - expect(html`${unsafeString} text`.value).eq( - '<&> text', - ) - expect(html`text ${unsafeString}`.value).eq( - 'text <&>', - ) - expect(html`${unsafeString}`.value).eq( - '<&>', - ) + expect(html`${unsafeString} text`.value).eq('<&> text') + expect(html`text ${unsafeString}`.value).eq('text <&>') + expect(html`${unsafeString}`.value).eq('<&>') }) it('should skip with FormattedString', () => { @@ -599,19 +503,11 @@ describe('HtmlMessageEntityParser', () => { const unsafeString = new FormattedString('<&>') expect(html`${unsafeString}`.value).eq('<&>') - expect(html`${unsafeString} ${unsafeString2}`.value).eq( - '<&> <&>', - ) - expect(html`${unsafeString} text`.value).eq( - '<&> text', - ) - expect(html`text ${unsafeString}`.value).eq( - 'text <&>', - ) + expect(html`${unsafeString} ${unsafeString2}`.value).eq('<&> <&>') + expect(html`${unsafeString} text`.value).eq('<&> text') + expect(html`text ${unsafeString}`.value).eq('text <&>') expect(html`${unsafeString}`.value).eq('<&>') - expect(html`${unsafeString} ${unsafeString2}`.value).eq( - '<&> <&>', - ) + expect(html`${unsafeString} ${unsafeString2}`.value).eq('<&> <&>') }) it('should error with incompatible FormattedString', () => { diff --git a/packages/http-proxy/index.ts b/packages/http-proxy/index.ts index b8914f86..e7bc45d9 100644 --- a/packages/http-proxy/index.ts +++ b/packages/http-proxy/index.ts @@ -3,13 +3,7 @@ import { connect as connectTcp } from 'net' import { connect as connectTls, SecureContextOptions } from 'tls' -import { - BaseTcpTransport, - IntermediatePacketCodec, - MtcuteError, - tl, - TransportState, -} from '@mtcute/core' +import { BaseTcpTransport, IntermediatePacketCodec, MtcuteError, tl, TransportState } from '@mtcute/core' /** * An error has occurred while connecting to an HTTP(s) proxy @@ -18,9 +12,7 @@ export class HttpProxyConnectionError extends Error { readonly proxy: HttpProxySettings constructor(proxy: HttpProxySettings, message: string) { - super( - `Error while connecting to ${proxy.host}:${proxy.port}: ${message}`, - ) + super(`Error while connecting to ${proxy.host}:${proxy.port}: ${message}`) this.proxy = proxy } } @@ -94,28 +86,15 @@ export abstract class BaseHttpProxyTcpTransport extends BaseTcpTransport { this._currentDc = dc this._socket = this._proxy.tls ? - connectTls( - this._proxy.port, - this._proxy.host, - this._proxy.tlsOptions, - this._onProxyConnected.bind(this), - ) : - connectTcp( - this._proxy.port, - this._proxy.host, - this._onProxyConnected.bind(this), - ) + connectTls(this._proxy.port, this._proxy.host, this._proxy.tlsOptions, this._onProxyConnected.bind(this)) : + connectTcp(this._proxy.port, this._proxy.host, this._onProxyConnected.bind(this)) this._socket.on('error', this.handleError.bind(this)) this._socket.on('close', this.close.bind(this)) } private _onProxyConnected() { - this.log.debug( - '[%s:%d] connected to proxy, sending CONNECT', - this._proxy.host, - this._proxy.port, - ) + this.log.debug('[%s:%d] connected to proxy, sending CONNECT', this._proxy.host, this._proxy.port) let ip = `${this._currentDc!.ipAddress}:${this._currentDc!.port}` if (this._currentDc!.ipv6) ip = `[${ip}]` @@ -131,8 +110,7 @@ export abstract class BaseHttpProxyTcpTransport extends BaseTcpTransport { if (this._proxy.password) { auth += ':' + this._proxy.password } - headers['Proxy-Authorization'] = - 'Basic ' + Buffer.from(auth).toString('base64') + headers['Proxy-Authorization'] = 'Basic ' + Buffer.from(auth).toString('base64') } headers['Proxy-Connection'] = 'Keep-Alive' @@ -143,12 +121,7 @@ export abstract class BaseHttpProxyTcpTransport extends BaseTcpTransport { this._socket!.write(packet) this._socket!.once('data', (msg) => { - this.log.debug( - '[%s:%d] CONNECT resulted in: %s', - this._proxy.host, - this._proxy.port, - msg, - ) + this.log.debug('[%s:%d] CONNECT resulted in: %s', this._proxy.host, this._proxy.port, msg) const [proto, code, name] = msg.toString().split(' ') @@ -156,10 +129,7 @@ export abstract class BaseHttpProxyTcpTransport extends BaseTcpTransport { // wtf? this._socket!.emit( 'error', - new HttpProxyConnectionError( - this._proxy, - `Server returned invalid protocol: ${proto}`, - ), + new HttpProxyConnectionError(this._proxy, `Server returned invalid protocol: ${proto}`), ) return @@ -168,10 +138,7 @@ export abstract class BaseHttpProxyTcpTransport extends BaseTcpTransport { if (code[0] !== '2') { this._socket!.emit( 'error', - new HttpProxyConnectionError( - this._proxy, - `Server returned error: ${code} ${name}`, - ), + new HttpProxyConnectionError(this._proxy, `Server returned error: ${code} ${name}`), ) return diff --git a/packages/i18n/src/index.ts b/packages/i18n/src/index.ts index f255e0e2..b8ee241f 100644 --- a/packages/i18n/src/index.ts +++ b/packages/i18n/src/index.ts @@ -1,10 +1,4 @@ -import { - I18nStrings, - I18nValue, - MtcuteI18nAdapter, - MtcuteI18nFunction, - OtherLanguageWrap, -} from './types' +import { I18nStrings, I18nValue, MtcuteI18nAdapter, MtcuteI18nFunction, OtherLanguageWrap } from './types' import { createI18nStringsIndex, extractLanguageFromUpdate } from './utils' export * from './types' @@ -52,8 +46,7 @@ export function createMtcuteI18n( } = params const indexes: Record> = {} - const fallbackIndex = (indexes[primaryLanguage.name] = - createI18nStringsIndex(primaryLanguage.strings)) + const fallbackIndex = (indexes[primaryLanguage.name] = createI18nStringsIndex(primaryLanguage.strings)) if (otherLanguages) { Object.keys(otherLanguages).forEach((lang) => { @@ -62,16 +55,10 @@ export function createMtcuteI18n( } if (!(defaultLanguage in indexes)) { - throw new TypeError( - 'defaultLanguage is not a registered language', - ) + throw new TypeError('defaultLanguage is not a registered language') } - const tr = ( - lang: Input | string | null, - key: string, - ...params: unknown[] - ) => { + const tr = (lang: Input | string | null, key: string, ...params: unknown[]) => { if (lang === null) lang = defaultLanguage if (typeof lang !== 'string') { diff --git a/packages/i18n/src/plurals/russian.ts b/packages/i18n/src/plurals/russian.ts index 9fe40c39..ed83c828 100644 --- a/packages/i18n/src/plurals/russian.ts +++ b/packages/i18n/src/plurals/russian.ts @@ -8,12 +8,7 @@ import { I18nValue, I18nValueDynamic } from '../types' * @param few Value for "few" (2 стола, 42 стола) * @param many Value for "many" (5 столов, 100 столов, 0 столов, нет столов) */ -export function pluralizeRussian( - n: number, - one: T, - few: T, - many: T, -): T { +export function pluralizeRussian(n: number, one: T, few: T, many: T): T { // reference: https://unicode-org.github.io/cldr-staging/charts/latest/supplemental/language_plural_rules.html#ru // one: 1 книга diff --git a/packages/i18n/src/types.ts b/packages/i18n/src/types.ts index ab4acd49..02ce4899 100644 --- a/packages/i18n/src/types.ts +++ b/packages/i18n/src/types.ts @@ -13,16 +13,12 @@ export type I18nValueLiteral = string | FormattedString * Dynamic translated value, represented by a * function resolving to a literal one */ -export type I18nValueDynamic = ( - ...args: Args -) => I18nValueLiteral +export type I18nValueDynamic = (...args: Args) => I18nValueLiteral /** * Translated value. Can either be actual value or a function resolving to one */ -export type I18nValue = - | I18nValueLiteral - | I18nValueDynamic +export type I18nValue = I18nValueLiteral | I18nValueDynamic /** * Strings dictionary @@ -43,10 +39,9 @@ type GetValueNested = K extends `${infer P}.${infer Q}` ? GetValueNested, Q> : SafeGet -type ExtractParameter = GetValueNested< - Strings, - K -> extends (...params: infer R) => I18nValueLiteral +type ExtractParameter = GetValueNested extends ( + ...params: infer R +) => I18nValueLiteral ? R : [] @@ -60,9 +55,7 @@ export type MtcuteI18nAdapter = (obj: Input) => string | null | undefined /** * Translation function. */ -export type MtcuteI18nFunction = < - K extends NestedKeysDelimited ->( +export type MtcuteI18nFunction = >( lang: Input | string | null, key: K, ...params: ExtractParameter diff --git a/packages/i18n/src/utils.ts b/packages/i18n/src/utils.ts index faaf2a25..6b596542 100644 --- a/packages/i18n/src/utils.ts +++ b/packages/i18n/src/utils.ts @@ -13,9 +13,7 @@ try { * * @param strings Strings object */ -export function createI18nStringsIndex( - strings: I18nStrings, -): Record { +export function createI18nStringsIndex(strings: I18nStrings): Record { const ret: Record = {} function add(obj: I18nStrings, prefix: string) { @@ -41,24 +39,18 @@ export function createI18nStringsIndex( * * @param update Update to extract language from */ -export function extractLanguageFromUpdate( - update: clientNs.ParsedUpdate['data'], -): string | null | undefined { +export function extractLanguageFromUpdate(update: clientNs.ParsedUpdate['data']): string | null | undefined { if (!client) { - throw new Error( - '@mtcute/client is not installed, you must provide your own adapter', - ) + throw new Error('@mtcute/client is not installed, you must provide your own adapter') } switch (update.constructor) { case client.Message: // if sender is Chat it will just be undefined - return ((update as clientNs.Message).sender as clientNs.User) - .language + return ((update as clientNs.Message).sender as clientNs.User).language case client.PollVoteUpdate: // if peer is Chat it will just be undefined - return ((update as clientNs.PollVoteUpdate).peer as clientNs.User) - .language + return ((update as clientNs.PollVoteUpdate).peer as clientNs.User).language case client.ChatMemberUpdate: case client.InlineQuery: case client.ChosenInlineResult: diff --git a/packages/i18n/tests/i18n.spec.ts b/packages/i18n/tests/i18n.spec.ts index cc5ab518..2bdeae55 100644 --- a/packages/i18n/tests/i18n.spec.ts +++ b/packages/i18n/tests/i18n.spec.ts @@ -20,12 +20,8 @@ describe('i18n', () => { }, }, plural: createPluralEnglish('a message', (n) => `${n} messages`), - plural2: createPluralEnglish( - 'a message', - (n: number, s: string) => `${n} messages from ${s}`, - ), - plural3: (n: number) => - `${n} ${pluralizeEnglish(n, 'message', 'messages')}`, + plural2: createPluralEnglish('a message', (n: number, s: string) => `${n} messages from ${s}`), + plural3: (n: number) => `${n} ${pluralizeEnglish(n, 'message', 'messages')}`, } const ru: OtherLanguageWrap = { direct: 'Привет', @@ -61,9 +57,7 @@ describe('i18n', () => { it('should work with function with args', () => { expect(tr('en', 'withArgs', '')).to.equal('Welcome ') expect(tr('en', 'withArgs', 'John')).to.equal('Welcome John') - expect(tr('en', 'withArgsObj', { name: 'John' })).to.equal( - 'Welcome John', - ) + expect(tr('en', 'withArgsObj', { name: 'John' })).to.equal('Welcome John') }) it('should work with nested values', () => { @@ -79,9 +73,7 @@ describe('i18n', () => { it('should fallback to primary language when string is not translated', () => { expect(tr('ru', 'fn')).to.equal('World') - expect(tr('ru', 'withArgsObj', { name: 'Ваня' })).to.equal( - 'Welcome Ваня', - ) + expect(tr('ru', 'withArgsObj', { name: 'Ваня' })).to.equal('Welcome Ваня') expect(tr('ru', 'nested.string')).to.equal('Hello') }) @@ -95,9 +87,7 @@ describe('i18n', () => { null as never, { _: 'message', peerId: { _: 'peerUser', userId: 1 } } as never, PeersIndex.from({ - users: [ - { _: 'user', id: 1, firstName: 'Пыня', langCode: 'ru' }, - ], + users: [{ _: 'user', id: 1, firstName: 'Пыня', langCode: 'ru' }], }), ) @@ -124,9 +114,7 @@ describe('i18n', () => { expect(tr('en', 'plural', 2)).to.equal('2 messages') expect(tr('en', 'plural2', 1, 'baka')).to.equal('a message') - expect(tr('en', 'plural2', 2, 'baka')).to.equal( - '2 messages from baka', - ) + expect(tr('en', 'plural2', 2, 'baka')).to.equal('2 messages from baka') expect(tr('en', 'plural3', 1)).to.equal('1 message') expect(tr('en', 'plural3', 2)).to.equal('2 messages') diff --git a/packages/i18n/tests/types.ts b/packages/i18n/tests/types.ts index 0893d116..0d85ba0f 100644 --- a/packages/i18n/tests/types.ts +++ b/packages/i18n/tests/types.ts @@ -3,11 +3,7 @@ // This file is never executed, only compiled import { Message } from '@mtcute/client' -import { - createMtcuteI18n, - OtherLanguageWrapExhaustive, - OtherLanguageWrap, -} from '../src' +import { createMtcuteI18n, OtherLanguageWrapExhaustive, OtherLanguageWrap } from '../src' const en = { basic: { diff --git a/packages/markdown-parser/src/index.ts b/packages/markdown-parser/src/index.ts index 62cf7fe0..22c6b11d 100644 --- a/packages/markdown-parser/src/index.ts +++ b/packages/markdown-parser/src/index.ts @@ -1,14 +1,8 @@ import Long from 'long' -import type { - FormattedString, - IMessageEntityParser, - MessageEntity, - tl, -} from '@mtcute/client' +import type { FormattedString, IMessageEntityParser, MessageEntity, tl } from '@mtcute/client' -const MENTION_REGEX = - /^tg:\/\/user\?id=(\d+)(?:&hash=(-?[0-9a-fA-F]+)(?:&|$)|&|$)/ +const MENTION_REGEX = /^tg:\/\/user\?id=(\d+)(?:&hash=(-?[0-9a-fA-F]+)(?:&|$)|&|$)/ const EMOJI_REGEX = /^tg:\/\/emoji\?id=(-?\d+)/ const TAG_BOLD = '**' @@ -31,13 +25,7 @@ const TO_BE_ESCAPED = /[*_\-~`[\\\]|]/g */ export function md( strings: TemplateStringsArray, - ...sub: ( - | string - | FormattedString<'markdown'> - | boolean - | undefined - | null - )[] + ...sub: (string | FormattedString<'markdown'> | boolean | undefined | null)[] ): FormattedString<'markdown'> { let str = '' sub.forEach((it, idx) => { @@ -154,9 +142,7 @@ export class MarkdownMessageEntityParser implements IMessageEntityParser { if (text[pos + 1] !== '(') { // [link text] // ignore this, and add opening [ - result = `${result.substr(0, ent.offset)}[${result.substr( - ent.offset, - )}]` + result = `${result.substr(0, ent.offset)}[${result.substr(ent.offset)}]` pos += 1 insideLink = false continue @@ -185,40 +171,24 @@ export class MarkdownMessageEntityParser implements IMessageEntityParser { const accessHash = m[2] if (accessHash) { - ( - ent as tl.Mutable - )._ = 'inputMessageEntityMentionName' - ;( - ent as tl.Mutable - ).userId = { + (ent as tl.Mutable)._ = + 'inputMessageEntityMentionName' + ;(ent as tl.Mutable).userId = { _: 'inputUser', userId, - accessHash: Long.fromString( - accessHash, - false, - 16, - ), + accessHash: Long.fromString(accessHash, false, 16), } } else { - ( - ent as tl.Mutable - )._ = 'messageEntityMentionName' - ;( - ent as tl.Mutable - ).userId = userId + (ent as tl.Mutable)._ = 'messageEntityMentionName' + ;(ent as tl.Mutable).userId = userId } } else if ((m = EMOJI_REGEX.exec(url))) { - (ent as tl.Mutable)._ = - 'messageEntityCustomEmoji' - ;( - ent as tl.Mutable - ).documentId = Long.fromString(m[1]) + (ent as tl.Mutable)._ = 'messageEntityCustomEmoji' + ;(ent as tl.Mutable).documentId = Long.fromString(m[1]) } else { if (url.match(/^\/\//)) url = 'http:' + url - ;(ent as tl.Mutable)._ = - 'messageEntityTextUrl' - ;(ent as tl.Mutable).url = - url + ;(ent as tl.Mutable)._ = 'messageEntityTextUrl' + ;(ent as tl.Mutable).url = url } entities.push(ent) } @@ -255,9 +225,7 @@ export class MarkdownMessageEntityParser implements IMessageEntityParser { pos += 1 if (pos > text.length) { - throw new Error( - 'Malformed PRE entity, expected LF after ```', - ) + throw new Error('Malformed PRE entity, expected LF after ```') } if (!('pre' in stacks)) stacks.pre = [] @@ -284,13 +252,7 @@ export class MarkdownMessageEntityParser implements IMessageEntityParser { if (c === text[pos + 1]) { // maybe (?) start or end of an entity - let type: - | 'Italic' - | 'Bold' - | 'Underline' - | 'Strike' - | 'Spoiler' - | null = null + let type: 'Italic' | 'Bold' | 'Underline' | 'Strike' | 'Spoiler' | null = null switch (c) { case '_': @@ -368,18 +330,12 @@ export class MarkdownMessageEntityParser implements IMessageEntityParser { // determine number of escape chars since the beginning of the string let escapedPos = 0 - while ( - escapedPos < escaped.length && - escaped[escapedPos] < start - ) { + while (escapedPos < escaped.length && escaped[escapedPos] < start) { escapedPos += 1 } start += escapedPos - while ( - escapedPos < escaped.length && - escaped[escapedPos] <= end - ) { + while (escapedPos < escaped.length && escaped[escapedPos] <= end) { escapedPos += 1 } end += escapedPos diff --git a/packages/markdown-parser/tests/markdown-parser.spec.ts b/packages/markdown-parser/tests/markdown-parser.spec.ts index 69fe572a..ebf70377 100644 --- a/packages/markdown-parser/tests/markdown-parser.spec.ts +++ b/packages/markdown-parser/tests/markdown-parser.spec.ts @@ -11,10 +11,7 @@ const createEntity = ( type: T, offset: number, length: number, - additional?: Omit< - tl.FindByName, - '_' | 'offset' | 'length' - >, + additional?: Omit, '_' | 'offset' | 'length'>, ): tl.TypeMessageEntity => { return { _: type, @@ -25,9 +22,7 @@ const createEntity = ( } const createEntities = (entities: tl.TypeMessageEntity[]): MessageEntity[] => { - return entities - .map((it) => MessageEntity._parse(it)) - .filter((it) => it !== null) as MessageEntity[] + return entities.map((it) => MessageEntity._parse(it)).filter((it) => it !== null) as MessageEntity[] } describe('MarkdownMessageEntityParser', () => { @@ -113,10 +108,7 @@ describe('MarkdownMessageEntityParser', () => { it('should support entities on the edges', () => { test( 'Hello, world', - [ - createEntity('messageEntityBold', 0, 5), - createEntity('messageEntityBold', 7, 5), - ], + [createEntity('messageEntityBold', 0, 5), createEntity('messageEntityBold', 7, 5)], '**Hello**, **world**', ) }) @@ -124,29 +116,19 @@ describe('MarkdownMessageEntityParser', () => { it('should clamp out-of-range entities', () => { test( 'Hello, world', - [ - createEntity('messageEntityBold', -2, 7), - createEntity('messageEntityBold', 7, 10), - ], + [createEntity('messageEntityBold', -2, 7), createEntity('messageEntityBold', 7, 10)], '**Hello**, **world**', ) }) it('should ignore entities outside the length', () => { - test( - 'Hello, world', - [createEntity('messageEntityBold', 50, 5)], - 'Hello, world', - ) + test('Hello, world', [createEntity('messageEntityBold', 50, 5)], 'Hello, world') }) it('should support entities followed by each other', () => { test( 'plain Hello, world plain', - [ - createEntity('messageEntityBold', 6, 6), - createEntity('messageEntityItalic', 12, 6), - ], + [createEntity('messageEntityBold', 6, 6), createEntity('messageEntityItalic', 12, 6)], [ 'plain **Hello,**__ world__ plain', // not the most obvious order, but who cares :D @@ -159,10 +141,7 @@ describe('MarkdownMessageEntityParser', () => { it('should support nested entities', () => { test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityItalic', 0, 24), - createEntity('messageEntityBold', 15, 8), - ], + [createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 15, 8)], '__Welcome to the **gym zone**!__', ) }) @@ -170,43 +149,22 @@ describe('MarkdownMessageEntityParser', () => { it('should support nested entities with the same edges', () => { test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityItalic', 0, 24), - createEntity('messageEntityBold', 15, 9), - ], - [ - '__Welcome to the **gym zone!**__', - '__Welcome to the **gym zone!__**', - ], + [createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 15, 9)], + ['__Welcome to the **gym zone!**__', '__Welcome to the **gym zone!__**'], ) test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityBold', 0, 24), - createEntity('messageEntityItalic', 15, 9), - ], - [ - '**Welcome to the __gym zone!__**', - '**Welcome to the __gym zone!**__', - ], + [createEntity('messageEntityBold', 0, 24), createEntity('messageEntityItalic', 15, 9)], + ['**Welcome to the __gym zone!__**', '**Welcome to the __gym zone!**__'], ) test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityItalic', 0, 24), - createEntity('messageEntityBold', 0, 7), - ], - [ - '__**Welcome** to the gym zone!__', - '**__Welcome** to the gym zone!__', - ], + [createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 0, 7)], + ['__**Welcome** to the gym zone!__', '**__Welcome** to the gym zone!__'], ) test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityItalic', 0, 24), - createEntity('messageEntityBold', 0, 24), - ], + [createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 0, 24)], [ '__**Welcome to the gym zone!**__', '__**Welcome to the gym zone!__**', @@ -219,10 +177,7 @@ describe('MarkdownMessageEntityParser', () => { it('should support overlapping entities', () => { test( 'Welcome to the gym zone!', - [ - createEntity('messageEntityItalic', 0, 14), - createEntity('messageEntityBold', 8, 10), - ], + [createEntity('messageEntityItalic', 0, 14), createEntity('messageEntityBold', 8, 10)], '__Welcome **to the__ gym** zone!', ) test( @@ -276,10 +231,7 @@ describe('MarkdownMessageEntityParser', () => { createEntity('messageEntityItalic', 18, 4), createEntity('messageEntityItalic', 9, 8), ], - '/* /*/* /*/*/* __/_ /_/_ /_/_/___ __/- /-/-__ /-/-/-'.replace( - /\//g, - '\\', - ), + '/* /*/* /*/*/* __/_ /_/_ /_/_/___ __/- /-/-__ /-/-/-'.replace(/\//g, '\\'), ) }) }) @@ -386,10 +338,7 @@ describe('MarkdownMessageEntityParser', () => { it('should support entities on the edges', () => { test( '**Hello**, **world**', - [ - createEntity('messageEntityBold', 0, 5), - createEntity('messageEntityBold', 7, 5), - ], + [createEntity('messageEntityBold', 0, 5), createEntity('messageEntityBold', 7, 5)], 'Hello, world', ) }) @@ -401,10 +350,7 @@ describe('MarkdownMessageEntityParser', () => { it('should support overlapping entities', () => { test( '__Welcome **to the__ gym** zone!', - [ - createEntity('messageEntityItalic', 0, 14), - createEntity('messageEntityBold', 8, 10), - ], + [createEntity('messageEntityItalic', 0, 14), createEntity('messageEntityBold', 8, 10)], 'Welcome to the gym zone!', ) @@ -442,14 +388,8 @@ describe('MarkdownMessageEntityParser', () => { it('should support entities followed by each other', () => { test( - [ - 'plain **Hello,**__ world__ plain', - 'plain **Hello,__** world__ plain', - ], - [ - createEntity('messageEntityBold', 6, 6), - createEntity('messageEntityItalic', 12, 6), - ], + ['plain **Hello,**__ world__ plain', 'plain **Hello,__** world__ plain'], + [createEntity('messageEntityBold', 6, 6), createEntity('messageEntityItalic', 12, 6)], 'plain Hello, world plain', ) }) @@ -457,10 +397,7 @@ describe('MarkdownMessageEntityParser', () => { it('should support nested entities', () => { test( '__Welcome to the **gym zone**!__', - [ - createEntity('messageEntityBold', 15, 8), - createEntity('messageEntityItalic', 0, 24), - ], + [createEntity('messageEntityBold', 15, 8), createEntity('messageEntityItalic', 0, 24)], 'Welcome to the gym zone!', ) @@ -490,70 +427,40 @@ describe('MarkdownMessageEntityParser', () => { // again, order of the entities depends on which closing tag goes first. test( '__Welcome to the **gym zone!**__', - [ - createEntity('messageEntityBold', 15, 9), - createEntity('messageEntityItalic', 0, 24), - ], + [createEntity('messageEntityBold', 15, 9), createEntity('messageEntityItalic', 0, 24)], 'Welcome to the gym zone!', ) test( '__Welcome to the **gym zone!__**', - [ - createEntity('messageEntityItalic', 0, 24), - createEntity('messageEntityBold', 15, 9), - ], + [createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 15, 9)], 'Welcome to the gym zone!', ) test( '**Welcome to the __gym zone!__**', - [ - createEntity('messageEntityItalic', 15, 9), - createEntity('messageEntityBold', 0, 24), - ], + [createEntity('messageEntityItalic', 15, 9), createEntity('messageEntityBold', 0, 24)], 'Welcome to the gym zone!', ) test( '**Welcome to the __gym zone!**__', - [ - createEntity('messageEntityBold', 0, 24), - createEntity('messageEntityItalic', 15, 9), - ], + [createEntity('messageEntityBold', 0, 24), createEntity('messageEntityItalic', 15, 9)], 'Welcome to the gym zone!', ) test( - [ - '__**Welcome** to the gym zone!__', - '**__Welcome** to the gym zone!__', - ], - [ - createEntity('messageEntityBold', 0, 7), - createEntity('messageEntityItalic', 0, 24), - ], + ['__**Welcome** to the gym zone!__', '**__Welcome** to the gym zone!__'], + [createEntity('messageEntityBold', 0, 7), createEntity('messageEntityItalic', 0, 24)], 'Welcome to the gym zone!', ) test( - [ - '__**Welcome to the gym zone!**__', - '**__Welcome to the gym zone!**__', - ], - [ - createEntity('messageEntityBold', 0, 24), - createEntity('messageEntityItalic', 0, 24), - ], + ['__**Welcome to the gym zone!**__', '**__Welcome to the gym zone!**__'], + [createEntity('messageEntityBold', 0, 24), createEntity('messageEntityItalic', 0, 24)], 'Welcome to the gym zone!', ) test( - [ - '__**Welcome to the gym zone!__**', - '**__Welcome to the gym zone!__**', - ], - [ - createEntity('messageEntityItalic', 0, 24), - createEntity('messageEntityBold', 0, 24), - ], + ['__**Welcome to the gym zone!__**', '**__Welcome to the gym zone!__**'], + [createEntity('messageEntityItalic', 0, 24), createEntity('messageEntityBold', 0, 24)], 'Welcome to the gym zone!', ) }) @@ -580,14 +487,8 @@ describe('MarkdownMessageEntityParser', () => { '* ** *** _ __ ___ - -- --- ~ ~~ ~~~ [ [[ ` `` ``` ```` \\ \\\\', ) test( - '/* /*/* /*/*/* __/_ /_/_ /_/_/___ __/- /-/-__ /-/-/-'.replace( - /\//g, - '\\', - ), - [ - createEntity('messageEntityItalic', 9, 8), - createEntity('messageEntityItalic', 18, 4), - ], + '/* /*/* /*/*/* __/_ /_/_ /_/_/___ __/- /-/-__ /-/-/-'.replace(/\//g, '\\'), + [createEntity('messageEntityItalic', 9, 8), createEntity('messageEntityItalic', 18, 4)], '* ** *** _ __ ___ - -- ---', ) }) @@ -597,34 +498,14 @@ describe('MarkdownMessageEntityParser', () => { }) it('should ignore unclosed tags', () => { - test( - 'plain ```\npre closed with single backtick`', - [], - 'plain pre closed with single backtick`', - ) - test( - 'plain ```\npre closed with single backtick\n`', - [], - 'plain pre closed with single backtick\n`', - ) + test('plain ```\npre closed with single backtick`', [], 'plain pre closed with single backtick`') + test('plain ```\npre closed with single backtick\n`', [], 'plain pre closed with single backtick\n`') - test( - 'plain ```\npre closed with double backticks`', - [], - 'plain pre closed with double backticks`', - ) - test( - 'plain ```\npre closed with double backticks\n`', - [], - 'plain pre closed with double backticks\n`', - ) + test('plain ```\npre closed with double backticks`', [], 'plain pre closed with double backticks`') + test('plain ```\npre closed with double backticks\n`', [], 'plain pre closed with double backticks\n`') test('plain __italic but unclosed', [], 'plain italic but unclosed') - test( - 'plain __italic and **also bold but both unclosed', - [], - 'plain italic and also bold but both unclosed', - ) + test('plain __italic and **also bold but both unclosed', [], 'plain italic and also bold but both unclosed') test( 'plain __italic and **also bold but italic closed__', [createEntity('messageEntityItalic', 6, 38)], @@ -638,8 +519,7 @@ describe('MarkdownMessageEntityParser', () => { }) describe('malformed input', () => { - const testThrows = (input: string) => - expect(() => parser.parse(input)).throws(Error) + const testThrows = (input: string) => expect(() => parser.parse(input)).throws(Error) it('should throw an error on malformed links', () => { testThrows('plain [link](https://google.com but unclosed') @@ -647,9 +527,7 @@ describe('MarkdownMessageEntityParser', () => { it('should throw an error on malformed pres', () => { testThrows('plain ```pre without linebreaks```') - testThrows( - 'plain ``` pre without linebreaks but with spaces instead ```', - ) + testThrows('plain ``` pre without linebreaks but with spaces instead ```') }) }) }) @@ -659,12 +537,8 @@ describe('MarkdownMessageEntityParser', () => { const unsafeString = '__[]__' expect(md`${unsafeString}`.value).eq('\\_\\_\\[\\]\\_\\_') - expect(md`${unsafeString} **text**`.value).eq( - '\\_\\_\\[\\]\\_\\_ **text**', - ) - expect(md`**text** ${unsafeString}`.value).eq( - '**text** \\_\\_\\[\\]\\_\\_', - ) + expect(md`${unsafeString} **text**`.value).eq('\\_\\_\\[\\]\\_\\_ **text**') + expect(md`**text** ${unsafeString}`.value).eq('**text** \\_\\_\\[\\]\\_\\_') expect(md`**${unsafeString}**`.value).eq('**\\_\\_\\[\\]\\_\\_**') }) @@ -673,14 +547,10 @@ describe('MarkdownMessageEntityParser', () => { const unsafeString = new FormattedString('__[]__') expect(md`${unsafeString}`.value).eq('__[]__') - expect(md`${unsafeString} ${unsafeString2}`.value).eq( - '__[]__ \\_\\_\\[\\]\\_\\_', - ) + expect(md`${unsafeString} ${unsafeString2}`.value).eq('__[]__ \\_\\_\\[\\]\\_\\_') expect(md`${unsafeString} **text**`.value).eq('__[]__ **text**') expect(md`**text** ${unsafeString}`.value).eq('**text** __[]__') - expect(md`**${unsafeString} ${unsafeString2}**`.value).eq( - '**__[]__ \\_\\_\\[\\]\\_\\_**', - ) + expect(md`**${unsafeString} ${unsafeString2}**`.value).eq('**__[]__ \\_\\_\\[\\]\\_\\_**') }) it('should error with incompatible FormattedString', () => { diff --git a/packages/mtproxy/fake-tls.ts b/packages/mtproxy/fake-tls.ts index c7b55f1f..ba787dfd 100644 --- a/packages/mtproxy/fake-tls.ts +++ b/packages/mtproxy/fake-tls.ts @@ -1,31 +1,17 @@ import bigInt, { BigInteger } from 'big-integer' import { IPacketCodec, WrappedCodec } from '@mtcute/core' -import { - bigIntToBuffer, - bufferToBigInt, - ICryptoProvider, - randomBytes, -} from '@mtcute/core/utils' +import { bigIntToBuffer, bufferToBigInt, ICryptoProvider, randomBytes } from '@mtcute/core/utils' const MAX_TLS_PACKET_LENGTH = 2878 const TLS_FIRST_PREFIX = Buffer.from('140303000101', 'hex') // ref: https://github.com/tdlib/td/blob/master/td/mtproto/TlsInit.cpp -const KEY_MOD = bigInt( - '7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed', - 16, -) +const KEY_MOD = bigInt('7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed', 16) // 2^255 - 19 -const QUAD_RES_MOD = bigInt( - '7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed', - 16, -) +const QUAD_RES_MOD = bigInt('7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed', 16) // (mod - 1) / 2 = 2^254 - 10 -const QUAD_RES_POW = bigInt( - '3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6', - 16, -) +const QUAD_RES_POW = bigInt('3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6', 16) function _getY2(x: BigInteger, mod: BigInteger): BigInteger { // returns y = x^3 + x^2 * 486662 + x @@ -77,12 +63,7 @@ function executeTlsOperations(h: TlsOperationHandler): void { h.random(32) h.string(Buffer.from('0020', 'hex')) h.grease(0) - h.string( - Buffer.from( - '130113021303c02bc02fc02cc030cca9cca8c013c014009c009d002f003501000193', - 'hex', - ), - ) + h.string(Buffer.from('130113021303c02bc02fc02cc030cca9cca8c013c014009c009d002f003501000193', 'hex')) h.grease(2) h.string(Buffer.from('00000000', 'hex')) h.beginScope() @@ -274,11 +255,7 @@ class TlsHelloWriter implements TlsOperationHandler { } /** @internal */ -export async function generateFakeTlsHeader( - domain: string, - secret: Buffer, - crypto: ICryptoProvider, -): Promise { +export async function generateFakeTlsHeader(domain: string, secret: Buffer, crypto: ICryptoProvider): Promise { const domainBuf = Buffer.from(domain) const writer = new TlsHelloWriter(517, domainBuf) @@ -330,10 +307,7 @@ export class FakeTlsPacketCodec extends WrappedCodec implements IPacketCodec { const ret: Buffer[] = [] while (packet.length) { - const buf = packet.slice( - 0, - MAX_TLS_PACKET_LENGTH - this._header.length, - ) + const buf = packet.slice(0, MAX_TLS_PACKET_LENGTH - this._header.length) packet = packet.slice(buf.length) ret.push(this._encodeTls(buf)) } @@ -350,13 +324,7 @@ export class FakeTlsPacketCodec extends WrappedCodec implements IPacketCodec { for (;;) { if (this._stream.length < 5) return - if ( - !( - this._stream[0] === 0x17 && - this._stream[1] === 0x03 && - this._stream[2] === 0x03 - ) - ) { + if (!(this._stream[0] === 0x17 && this._stream[1] === 0x03 && this._stream[2] === 0x03)) { this.emit('error', new Error('Invalid TLS header')) return diff --git a/packages/mtproxy/index.ts b/packages/mtproxy/index.ts index a57d78f6..de3551c0 100644 --- a/packages/mtproxy/index.ts +++ b/packages/mtproxy/index.ts @@ -39,10 +39,7 @@ export interface MtProxySettings { } const MAX_DOMAIN_LENGTH = 182 // must be small enough not to overflow TLS-hello length -const TLS_START = [ - Buffer.from('160303', 'hex'), - Buffer.from('140303000101170303', 'hex'), -] +const TLS_START = [Buffer.from('160303', 'hex'), Buffer.from('140303000101170303', 'hex')] /** * TCP transport that connects via an MTProxy @@ -138,10 +135,7 @@ export class MtProxyTcpTransport extends BaseTcpTransport { this._packetCodec = new ObfuscatedPacketCodec(inner, proxy) } else { this._packetCodec = new FakeTlsPacketCodec( - new ObfuscatedPacketCodec( - new PaddedIntermediatePacketCodec(), - proxy, - ), + new ObfuscatedPacketCodec(new PaddedIntermediatePacketCodec(), proxy), ) } @@ -177,11 +171,7 @@ export class MtProxyTcpTransport extends BaseTcpTransport { private async _handleConnectFakeTls(): Promise { try { - const hello = await generateFakeTlsHeader( - this._fakeTlsDomain!, - this._rawSecret, - this._crypto, - ) + const hello = await generateFakeTlsHeader(this._fakeTlsDomain!, this._rawSecret, this._crypto) const helloRand = hello.slice(11, 11 + 32) const checkHelloResponse = async (buf: Buffer): Promise => { @@ -193,9 +183,7 @@ export class MtProxyTcpTransport extends BaseTcpTransport { } if (first.compare(first, 0, first.length) !== 0) { - throw new MtSecurityError( - 'First part of hello response is invalid', - ) + throw new MtSecurityError('First part of hello response is invalid') } buf = buf.slice(first.length) @@ -211,12 +199,7 @@ export class MtProxyTcpTransport extends BaseTcpTransport { const respRand = resp.slice(11, 11 + 32) const hash = await this._crypto.hmacSha256( - Buffer.concat([ - helloRand, - resp.slice(0, 11), - Buffer.alloc(32, 0), - resp.slice(11 + 32), - ]), + Buffer.concat([helloRand, resp.slice(0, 11), Buffer.alloc(32, 0), resp.slice(11 + 32)]), this._rawSecret, ) @@ -229,9 +212,7 @@ export class MtProxyTcpTransport extends BaseTcpTransport { checkHelloResponse(buf) .then(() => { this._socket!.off('data', packetHandler) - this._socket!.on('data', (data) => - this._packetCodec.feed(data), - ) + this._socket!.on('data', (data) => this._packetCodec.feed(data)) return this.handleConnect() }) diff --git a/packages/node/index.ts b/packages/node/index.ts index 9e61ca38..b26cc87c 100644 --- a/packages/node/index.ts +++ b/packages/node/index.ts @@ -20,8 +20,7 @@ try { nativeCrypto = require('@mtcute/crypto-node').NodeNativeCryptoProvider } catch (e) {} -export interface NodeTelegramClientOptions - extends Omit { +export interface NodeTelegramClientOptions extends Omit { /** * Default parse mode to use. * diff --git a/packages/socks-proxy/index.ts b/packages/socks-proxy/index.ts index 8566e09d..2175b0b4 100644 --- a/packages/socks-proxy/index.ts +++ b/packages/socks-proxy/index.ts @@ -21,9 +21,7 @@ export class SocksProxyConnectionError extends Error { readonly proxy: SocksProxySettings constructor(proxy: SocksProxySettings, message: string) { - super( - `Error while connecting to ${proxy.host}:${proxy.port}: ${message}`, - ) + super(`Error while connecting to ${proxy.host}:${proxy.port}: ${message}`) this.proxy = proxy } } @@ -77,11 +75,7 @@ function writeIpv4(ip: string, buf: Buffer, offset: number): void { } } -function buildSocks4ConnectRequest( - ip: string, - port: number, - username = '', -): Buffer { +function buildSocks4ConnectRequest(ip: string, port: number, username = ''): Buffer { const userId = Buffer.from(username) const buf = Buffer.alloc(9 + userId.length) @@ -117,14 +111,10 @@ function buildSocks5Auth(username: string, password: string) { const passwordBuf = Buffer.from(password) if (usernameBuf.length > 255) { - throw new MtArgumentError( - `Too long username (${usernameBuf.length} > 255)`, - ) + throw new MtArgumentError(`Too long username (${usernameBuf.length} > 255)`) } if (passwordBuf.length > 255) { - throw new MtArgumentError( - `Too long password (${passwordBuf.length} > 255)`, - ) + throw new MtArgumentError(`Too long password (${passwordBuf.length} > 255)`) } const buf = Buffer.alloc(3 + usernameBuf.length + passwordBuf.length) @@ -203,11 +193,7 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport { constructor(proxy: SocksProxySettings) { super() - if ( - proxy.version != null && - proxy.version !== 4 && - proxy.version !== 5 - ) { + if (proxy.version != null && proxy.version !== 4 && proxy.version !== 5) { throw new SocksProxyConnectionError( proxy, @@ -232,11 +218,7 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport { this._state = TransportState.Connecting this._currentDc = dc - this._socket = connect( - this._proxy.port, - this._proxy.host, - this._onProxyConnected.bind(this), - ) + this._socket = connect(this._proxy.port, this._proxy.host, this._onProxyConnected.bind(this)) this._socket.on('error', this.handleError.bind(this)) this._socket.on('close', this.close.bind(this)) @@ -251,54 +233,31 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport { // VER, must be 4 this._socket!.emit( 'error', - new SocksProxyConnectionError( - this._proxy, - `Server returned version ${msg[0]}`, - ), + new SocksProxyConnectionError(this._proxy, `Server returned version ${msg[0]}`), ) return } const code = msg[1] - this.log.debug( - '[%s:%d] CONNECT returned code %d', - this._proxy.host, - this._proxy.port, - code, - ) + this.log.debug('[%s:%d] CONNECT returned code %d', this._proxy.host, this._proxy.port, code) if (code === 0x5a) { this._socket!.off('data', packetHandler) - this._socket!.on('data', (data) => - this._packetCodec.feed(data), - ) + this._socket!.on('data', (data) => this._packetCodec.feed(data)) this.handleConnect() } else { const msg = - code in SOCKS4_ERRORS ? - SOCKS4_ERRORS[code] : - `Unknown error code: 0x${code.toString(16)}` - this._socket!.emit( - 'error', - new SocksProxyConnectionError(this._proxy, msg), - ) + code in SOCKS4_ERRORS ? SOCKS4_ERRORS[code] : `Unknown error code: 0x${code.toString(16)}` + this._socket!.emit('error', new SocksProxyConnectionError(this._proxy, msg)) } } - this.log.debug( - '[%s:%d] connected to proxy, sending CONNECT', - this._proxy.host, - this._proxy.port, - ) + this.log.debug('[%s:%d] connected to proxy, sending CONNECT', this._proxy.host, this._proxy.port) try { this._socket!.write( - buildSocks4ConnectRequest( - this._currentDc!.ipAddress, - this._currentDc!.port, - this._proxy.user, - ), + buildSocks4ConnectRequest(this._currentDc!.ipAddress, this._currentDc!.port, this._proxy.user), ) } catch (e) { this._socket!.emit('error', e) @@ -307,19 +266,11 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport { let state: 'greeting' | 'auth' | 'connect' = 'greeting' const sendConnect = () => { - this.log.debug( - '[%s:%d] sending CONNECT', - this._proxy.host, - this._proxy.port, - ) + this.log.debug('[%s:%d] sending CONNECT', this._proxy.host, this._proxy.port) try { this._socket!.write( - buildSocks5Connect( - this._currentDc!.ipAddress, - this._currentDc!.port, - this._currentDc!.ipv6, - ), + buildSocks5Connect(this._currentDc!.ipAddress, this._currentDc!.port, this._currentDc!.ipv6), ) state = 'connect' } catch (e) { @@ -334,10 +285,7 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport { // VER, must be 5 this._socket!.emit( 'error', - new SocksProxyConnectionError( - this._proxy, - `Server returned version ${msg[0]}`, - ), + new SocksProxyConnectionError(this._proxy, `Server returned version ${msg[0]}`), ) return @@ -359,10 +307,7 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport { break case 0x02: // Username/password - if ( - !this._proxy.user || - !this._proxy.password - ) { + if (!this._proxy.user || !this._proxy.password) { // should not happen this._socket!.emit( 'error', @@ -375,12 +320,7 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport { } try { - this._socket!.write( - buildSocks5Auth( - this._proxy.user, - this._proxy.password, - ), - ) + this._socket!.write(buildSocks5Auth(this._proxy.user, this._proxy.password)) state = 'auth' } catch (e) { this._socket!.emit('error', e) @@ -406,21 +346,13 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport { // VER of auth, must be 1 this._socket!.emit( 'error', - new SocksProxyConnectionError( - this._proxy, - `Server returned version ${msg[0]}`, - ), + new SocksProxyConnectionError(this._proxy, `Server returned version ${msg[0]}`), ) return } - this.log.debug( - '[%s:%d] AUTH returned code %d', - this._proxy.host, - this._proxy.port, - msg[1], - ) + this.log.debug('[%s:%d] AUTH returned code %d', this._proxy.host, this._proxy.port, msg[1]) if (msg[1] === 0x00) { // success @@ -428,10 +360,7 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport { } else { this._socket!.emit( 'error', - new SocksProxyConnectionError( - this._proxy, - 'Authentication failure', - ), + new SocksProxyConnectionError(this._proxy, 'Authentication failure'), ) } break @@ -441,10 +370,7 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport { // VER, must be 5 this._socket!.emit( 'error', - new SocksProxyConnectionError( - this._proxy, - `Server returned version ${msg[0]}`, - ), + new SocksProxyConnectionError(this._proxy, `Server returned version ${msg[0]}`), ) return @@ -452,31 +378,19 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport { const code = msg[1] - this.log.debug( - '[%s:%d] CONNECT returned code %d', - this._proxy.host, - this._proxy.port, - code, - ) + this.log.debug('[%s:%d] CONNECT returned code %d', this._proxy.host, this._proxy.port, code) if (code === 0x00) { // Request granted this._socket!.off('data', packetHandler) - this._socket!.on('data', (data) => - this._packetCodec.feed(data), - ) + this._socket!.on('data', (data) => this._packetCodec.feed(data)) this.handleConnect() } else { const msg = code in SOCKS5_ERRORS ? SOCKS5_ERRORS[code] : - `Unknown error code: 0x${code.toString( - 16, - )}` - this._socket!.emit( - 'error', - new SocksProxyConnectionError(this._proxy, msg), - ) + `Unknown error code: 0x${code.toString(16)}` + this._socket!.emit('error', new SocksProxyConnectionError(this._proxy, msg)) } break } @@ -485,18 +399,10 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport { } } - this.log.debug( - '[%s:%d] connected to proxy, sending GREETING', - this._proxy.host, - this._proxy.port, - ) + this.log.debug('[%s:%d] connected to proxy, sending GREETING', this._proxy.host, this._proxy.port) try { - this._socket!.write( - buildSocks5Greeting( - Boolean(this._proxy.user && this._proxy.password), - ), - ) + this._socket!.write(buildSocks5Greeting(Boolean(this._proxy.user && this._proxy.password))) } catch (e) { this._socket!.emit('error', e) } diff --git a/packages/sqlite/index.ts b/packages/sqlite/index.ts index 446cafc4..a39f38f3 100644 --- a/packages/sqlite/index.ts +++ b/packages/sqlite/index.ts @@ -11,20 +11,12 @@ import { TlWriterMap, toggleChannelIdMark, } from '@mtcute/core' -import { - Logger, - longFromFastString, - longToFastString, - LruMap, - throttle, -} from '@mtcute/core/utils' +import { Logger, longFromFastString, longToFastString, LruMap, throttle } from '@mtcute/core/utils' import { IStateStorage } from '@mtcute/dispatcher' // todo: add testMode to "self" -function getInputPeer( - row: SqliteEntity | ITelegramStorage.PeerInfo, -): tl.TypeInputPeer { +function getInputPeer(row: SqliteEntity | ITelegramStorage.PeerInfo): tl.TypeInputPeer { const id = row.id switch (row.type) { @@ -32,10 +24,7 @@ function getInputPeer( return { _: 'inputPeerUser', userId: id, - accessHash: - 'accessHash' in row ? - row.accessHash : - longFromFastString(row.hash), + accessHash: 'accessHash' in row ? row.accessHash : longFromFastString(row.hash), } case 'chat': return { @@ -46,10 +35,7 @@ function getInputPeer( return { _: 'inputPeerChannel', channelId: toggleChannelIdMark(id), - accessHash: - 'accessHash' in row ? - row.accessHash : - longFromFastString(row.hash), + accessHash: 'accessHash' in row ? row.accessHash : longFromFastString(row.hash), } } @@ -144,16 +130,13 @@ const STATEMENTS = { delKv: 'delete from kv where key = ?', getState: 'select value, expires from state where key = ?', - setState: - 'insert or replace into state (key, value, expires) values (?, ?, ?)', + setState: 'insert or replace into state (key, value, expires) values (?, ?, ?)', delState: 'delete from state where key = ?', getAuth: 'select key from auth_keys where dc = ?', - getAuthTemp: - 'select key from temp_auth_keys where dc = ? and idx = ? and expires > ?', + getAuthTemp: 'select key from temp_auth_keys where dc = ? and idx = ? and expires > ?', setAuth: 'insert or replace into auth_keys (dc, key) values (?, ?)', - setAuthTemp: - 'insert or replace into temp_auth_keys (dc, idx, key, expires) values (?, ?, ?, ?)', + setAuthTemp: 'insert or replace into temp_auth_keys (dc, idx, key, expires) values (?, ?, ?, ?)', delAuth: 'delete from auth_keys where dc = ?', delAuthTemp: 'delete from temp_auth_keys where dc = ? and idx = ?', delAllAuthTemp: 'delete from temp_auth_keys where dc = ?', @@ -162,8 +145,7 @@ const STATEMENTS = { setPts: 'insert or replace into pts (channel_id, pts) values (?, ?)', updateUpdated: 'update entities set updated = ? where id = ?', - updateCachedEnt: - 'update entities set username = ?, phone = ?, updated = ?, "full" = ? where id = ?', + updateCachedEnt: 'update entities set username = ?, phone = ?, updated = ?, "full" = ? where id = ?', upsertEnt: 'insert or replace into entities (id, hash, type, username, phone, updated, "full") values (?, ?, ?, ?, ?, ?, ?)', getEntById: 'select * from entities where id = ?', @@ -365,8 +347,7 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { } private _setToKv(key: string, value: unknown, now = false): void { - const query = - value === null ? this._statements.delKv : this._statements.setKv + const query = value === null ? this._statements.delKv : this._statements.setKv const params = value === null ? [key] : [key, JSON.stringify(value)] if (now) { @@ -383,9 +364,7 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { if (from < 2 || from > CURRENT_VERSION) { // 1 version was skipped during development // yes i am too lazy to make auto-migrations for them - throw new Error( - 'Unsupported session version, please migrate manually', - ) + throw new Error('Unsupported session version, please migrate manually') } if (from === 2) { @@ -396,22 +375,16 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { if (from === 3) { // media dc support added - const oldDc = this._db - .prepare("select value from kv where key = 'def_dc'") - .get() + const oldDc = this._db.prepare("select value from kv where key = 'def_dc'").get() if (oldDc) { - const oldDcValue = JSON.parse( - (oldDc as { value: string }).value, - ) as tl.RawDcOption - this._db - .prepare("update kv set value = ? where key = 'def_dc'") - .run([ - JSON.stringify({ - main: oldDcValue, - media: oldDcValue, - }), - ]) + const oldDcValue = JSON.parse((oldDc as { value: string }).value) as tl.RawDcOption + this._db.prepare("update kv set value = ? where key = 'def_dc'").run([ + JSON.stringify({ + main: oldDcValue, + media: oldDcValue, + }), + ]) } from = 4 } @@ -425,32 +398,23 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { private _initializeStatements(): void { this._statements = {} as unknown as typeof this._statements Object.entries(STATEMENTS).forEach(([name, sql]) => { - this._statements[name as keyof typeof this._statements] = - this._db.prepare(sql) + this._statements[name as keyof typeof this._statements] = this._db.prepare(sql) }) } private _initialize(): void { - const hasTables = this._db - .prepare( - "select name from sqlite_master where type = 'table' and name = 'kv'", - ) - .get() + const hasTables = this._db.prepare("select name from sqlite_master where type = 'table' and name = 'kv'").get() if (hasTables) { // tables already exist, check version - const versionResult = this._db - .prepare("select value from kv where key = 'ver'") - .get() + const versionResult = this._db.prepare("select value from kv where key = 'ver'").get() const version = Number((versionResult as { value: number }).value) this.log.debug('current db version = %d', version) if (version < CURRENT_VERSION) { this._upgradeDatabase(version) - this._db - .prepare("update kv set value = ? where key = 'ver'") - .run(CURRENT_VERSION) + this._db.prepare("update kv set value = ? where key = 'ver'").run(CURRENT_VERSION) } // prepared statements expect latest schema, so we need to upgrade first @@ -471,10 +435,7 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { load(): void { this._db = sqlite3(this._filename, { - verbose: - this.log.mgr.level === 5 ? - (this.log.verbose as Options['verbose']) : - undefined, + verbose: this.log.mgr.level === 5 ? (this.log.verbose as Options['verbose']) : undefined, }) this._initialize() @@ -485,13 +446,11 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { } // helper methods - this._runMany = this._db.transaction( - (stmts: [sqlite3.Statement, unknown[]][]) => { - stmts.forEach((stmt) => { - stmt[0].run(stmt[1]) - }) - }, - ) + this._runMany = this._db.transaction((stmts: [sqlite3.Statement, unknown[]][]) => { + stmts.forEach((stmt) => { + stmt[0].run(stmt[1]) + }) + }) this._updateManyPeers = this._db.transaction((data: unknown[][]) => { data.forEach((it: unknown) => { @@ -499,10 +458,7 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { }) }) - this._vacuumTimeout = setInterval( - this._vacuum.bind(this), - this._vacuumInterval, - ) + this._vacuumTimeout = setInterval(this._vacuum.bind(this), this._vacuumInterval) } save(): void { @@ -550,25 +506,15 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { ]) } - setTempAuthKeyFor( - dcId: number, - index: number, - key: Buffer | null, - expires: number, - ): void { + setTempAuthKeyFor(dcId: number, index: number, key: Buffer | null, expires: number): void { this._pending.push([ - key === null ? - this._statements.delAuthTemp : - this._statements.setAuthTemp, + key === null ? this._statements.delAuthTemp : this._statements.setAuthTemp, key === null ? [dcId, index] : [dcId, index, key, expires], ]) } dropAuthKeysFor(dcId: number): void { - this._pending.push( - [this._statements.delAuth, [dcId]], - [this._statements.delAllAuthTemp, [dcId]], - ) + this._pending.push([this._statements.delAuth, [dcId]], [this._statements.delAllAuthTemp, [dcId]]) } getSelf(): ITelegramStorage.SelfInfo | null { @@ -623,11 +569,7 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { peers.forEach((peer) => { const cached = this._cache?.get(peer.id) - if ( - cached && - 'accessHash' in cached.peer && - cached.peer.accessHash.eq(peer.accessHash) - ) { + if (cached && 'accessHash' in cached.peer && cached.peer.accessHash.eq(peer.accessHash)) { // when entity is cached and hash is the same, an update query is needed, // since some field in the full entity might have changed, or the username/phone // @@ -660,10 +602,7 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { peer.username, peer.phone, Date.now(), - TlBinaryWriter.serializeObject( - this.writerMap, - peer.full, - ), + TlBinaryWriter.serializeObject(this.writerMap, peer.full), ], ]) this._addToCache(peer.id, { @@ -678,9 +617,7 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { const cached = this._cache?.get(peerId) if (cached) return cached.peer - const row = this._statements.getEntById.get( - peerId, - ) as SqliteEntity | null + const row = this._statements.getEntById.get(peerId) as SqliteEntity | null if (row) { const peer = getInputPeer(row) @@ -696,9 +633,7 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { } getPeerByPhone(phone: string): tl.TypeInputPeer | null { - const row = this._statements.getEntByPhone.get( - phone, - ) as SqliteEntity | null + const row = this._statements.getEntByPhone.get(phone) as SqliteEntity | null if (row) { const peer = getInputPeer(row) @@ -714,9 +649,7 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { } getPeerByUsername(username: string): tl.TypeInputPeer | null { - const row = this._statements.getEntByUser.get( - username.toLowerCase(), - ) as SqliteEntity | null + const row = this._statements.getEntByUser.get(username.toLowerCase()) as SqliteEntity | null if (!row || Date.now() - row.updated > USERNAME_TTL) return null if (row) { @@ -789,11 +722,7 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { } this._fsmCache?.set(key, item) - this._statements.setState.run( - key, - parse ? JSON.stringify(item.value) : item.value, - item.expires, - ) + this._statements.setState.run(key, parse ? JSON.stringify(item.value) : item.value, item.expires) } deleteState(key: string): void { @@ -837,11 +766,7 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { value: limit, } - this._statements.setState.run( - `$rate_limit_${key}`, - item.value, - item.expires, - ) + this._statements.setState.run(`$rate_limit_${key}`, item.value, item.expires) this._rlCache?.set(key, item) return [item.value, item.expires!] @@ -850,11 +775,7 @@ export class SqliteStorage implements ITelegramStorage, IStateStorage { if (val.value > 0) { val.value -= 1 - this._statements.setState.run( - `$rate_limit_${key}`, - val.value, - val.expires, - ) + this._statements.setState.run(`$rate_limit_${key}`, val.value, val.expires) if (!cached) { // add to cache diff --git a/packages/tl-runtime/src/platform/gzip.ts b/packages/tl-runtime/src/platform/gzip.ts index c27a38c8..13d5e393 100644 --- a/packages/tl-runtime/src/platform/gzip.ts +++ b/packages/tl-runtime/src/platform/gzip.ts @@ -22,8 +22,8 @@ export function gzipDeflate(buf: Buffer, maxRatio?: number): Buffer | null { return deflateSync(buf, { maxOutputLength: Math.floor(buf.length * maxRatio), }) - // hot path, avoid additional runtime checks - // eslint-disable-next-line @typescript-eslint/no-explicit-any + // hot path, avoid additional runtime checks + // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (e: any) { if (e.code === 'ERR_BUFFER_TOO_LARGE') { return null diff --git a/packages/tl-runtime/src/platform/gzip.web.ts b/packages/tl-runtime/src/platform/gzip.web.ts index 128ca0ee..5d39827a 100644 --- a/packages/tl-runtime/src/platform/gzip.web.ts +++ b/packages/tl-runtime/src/platform/gzip.web.ts @@ -1,9 +1,7 @@ import { Data, Deflate, inflate } from 'pako' export function typedArrayToBuffer(arr: NodeJS.TypedArray): Buffer { - return ArrayBuffer.isView(arr) ? - Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength) : - Buffer.from(arr) + return ArrayBuffer.isView(arr) ? Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength) : Buffer.from(arr) } export function gzipInflate(buf: Buffer): Buffer { @@ -33,9 +31,7 @@ class DeflateLimited extends Deflate { } export function gzipDeflate(buf: Buffer, maxRatio?: number): Buffer | null { - const deflator = maxRatio ? - new DeflateLimited(Math.floor(buf.length * maxRatio)) : - new Deflate() + const deflator = maxRatio ? new DeflateLimited(Math.floor(buf.length * maxRatio)) : new Deflate() try { deflator.push(buf, true) diff --git a/packages/tl-runtime/src/reader.ts b/packages/tl-runtime/src/reader.ts index 11a78e9a..7a2992b1 100644 --- a/packages/tl-runtime/src/reader.ts +++ b/packages/tl-runtime/src/reader.ts @@ -42,11 +42,7 @@ export class TlBinaryReader { * @param data Buffer to read from * @param start Position to start reading from */ - constructor( - readonly objectsMap: TlReaderMap | undefined, - data: Buffer, - start = 0, - ) { + constructor(readonly objectsMap: TlReaderMap | undefined, data: Buffer, start = 0) { this.data = data this.pos = start } @@ -68,11 +64,7 @@ export class TlBinaryReader { * @param data Buffer to read from * @param start Position to start reading from */ - static deserializeObject( - objectsMap: TlReaderMap, - data: Buffer, - start = 0, - ): T { + static deserializeObject(objectsMap: TlReaderMap, data: Buffer, start = 0): T { return new TlBinaryReader(objectsMap, data, start).object() as T } @@ -100,9 +92,7 @@ export class TlBinaryReader { int53(): number { // inlined toNumber from Long - const res = - (this.data.readInt32LE(this.pos) >>> 0) + - TWO_PWR_32_DBL * this.data.readInt32LE(this.pos + 4) + const res = (this.data.readInt32LE(this.pos) >>> 0) + TWO_PWR_32_DBL * this.data.readInt32LE(this.pos + 4) this.pos += 8 return res @@ -135,9 +125,7 @@ export class TlBinaryReader { const val = this.uint() if (val === 0xbc799737) return false if (val === 0x997275b5) return true - throw new Error( - `Expected either boolTrue or boolFalse, got 0x${val.toString(16)}`, - ) + throw new Error(`Expected either boolTrue or boolFalse, got 0x${val.toString(16)}`) } /** @@ -164,10 +152,7 @@ export class TlBinaryReader { let padding if (firstByte === 254) { - length = - this.data[this.pos++] | - (this.data[this.pos++] << 8) | - (this.data[this.pos++] << 16) + length = this.data[this.pos++] | (this.data[this.pos++] << 8) | (this.data[this.pos++] << 16) padding = length % 4 } else { length = firstByte @@ -208,9 +193,7 @@ export class TlBinaryReader { this.seek(-4) const pos = this.pos const error = new TypeError( - `Unknown object id: 0x${id.toString( - 16, - )}. Content: ${this.raw().toString('hex')}`, + `Unknown object id: 0x${id.toString(16)}. Content: ${this.raw().toString('hex')}`, ) this.pos = pos throw error @@ -220,18 +203,13 @@ export class TlBinaryReader { } gzip(): unknown { - return new TlBinaryReader( - this.objectsMap, - gzipInflate(this.bytes()), - ).object() + return new TlBinaryReader(this.objectsMap, gzipInflate(this.bytes())).object() } vector(reader = this.object, bare = false): unknown[] { if (!bare) { if (this.uint() !== 0x1cb5c415) { - throw new Error( - 'Invalid object code, expected 0x1cb5c415 (vector)', - ) + throw new Error('Invalid object code, expected 0x1cb5c415 (vector)') } } diff --git a/packages/tl-runtime/src/writer.ts b/packages/tl-runtime/src/writer.ts index fd0107cc..1f25f8fd 100644 --- a/packages/tl-runtime/src/writer.ts +++ b/packages/tl-runtime/src/writer.ts @@ -33,10 +33,7 @@ export class TlSerializationCounter { * @param objectMap Writers map * @param obj Object to count bytes for */ - static countNeededBytes( - objectMap: TlWriterMap, - obj: { _: string }, - ): number { + static countNeededBytes(objectMap: TlWriterMap, obj: { _: string }): number { const cnt = new TlSerializationCounter(objectMap) cnt.object(obj) @@ -112,8 +109,7 @@ export class TlSerializationCounter { } bytes(val: Buffer): void { - this.count += - TlSerializationCounter.countBytesOverhead(val.length) + val.length + this.count += TlSerializationCounter.countBytesOverhead(val.length) + val.length } string(val: string): void { @@ -151,11 +147,7 @@ export class TlBinaryWriter { * @param buffer Buffer to write to * @param start Position to start writing at */ - constructor( - readonly objectMap: TlWriterMap | undefined, - buffer: Buffer, - start = 0, - ) { + constructor(readonly objectMap: TlWriterMap | undefined, buffer: Buffer, start = 0) { this.buffer = buffer this.pos = start } @@ -166,10 +158,7 @@ export class TlBinaryWriter { * @param objectMap Writers map * @param size Size of the writer's buffer */ - static alloc( - objectMap: TlWriterMap | undefined, - size: number, - ): TlBinaryWriter { + static alloc(objectMap: TlWriterMap | undefined, size: number): TlBinaryWriter { return new TlBinaryWriter(objectMap, Buffer.allocUnsafe(size)) } @@ -200,15 +189,9 @@ export class TlBinaryWriter { * @param obj Object to serialize * @param knownSize In case the size is known, pass it here */ - static serializeObject( - objectMap: TlWriterMap, - obj: { _: string }, - knownSize = -1, - ): Buffer { + static serializeObject(objectMap: TlWriterMap, obj: { _: string }, knownSize = -1): Buffer { if (knownSize === -1) { - knownSize = - objectMap._staticSize[obj._] || - TlSerializationCounter.countNeededBytes(objectMap, obj) + knownSize = objectMap._staticSize[obj._] || TlSerializationCounter.countNeededBytes(objectMap, obj) } const writer = TlBinaryWriter.alloc(objectMap, knownSize) @@ -233,10 +216,7 @@ export class TlBinaryWriter { this.buffer.writeInt32LE(val % TWO_PWR_32_DBL | 0, this.pos) if (val < 0) { - this.buffer.writeInt32LE( - (val / TWO_PWR_32_DBL - 1) | 0, - this.pos + 4, - ) + this.buffer.writeInt32LE((val / TWO_PWR_32_DBL - 1) | 0, this.pos + 4) } else { this.buffer.writeInt32LE((val / TWO_PWR_32_DBL) | 0, this.pos + 4) } @@ -326,11 +306,7 @@ export class TlBinaryWriter { fn(this, obj) } - vector( - fn: (item: unknown, bare?: boolean) => void, - val: unknown[], - bare?: boolean, - ): void { + vector(fn: (item: unknown, bare?: boolean) => void, val: unknown[], bare?: boolean): void { if (!bare) this.uint(0x1cb5c415) this.uint(val.length) diff --git a/packages/tl-runtime/tests/binary-reader.spec.ts b/packages/tl-runtime/tests/binary-reader.spec.ts index d68c7d87..f58c3bf1 100644 --- a/packages/tl-runtime/tests/binary-reader.spec.ts +++ b/packages/tl-runtime/tests/binary-reader.spec.ts @@ -11,129 +11,60 @@ describe('TlBinaryReader', () => { it('should read int32', () => { expect(TlBinaryReader.manual(Buffer.from([0, 0, 0, 0])).int()).eq(0) expect(TlBinaryReader.manual(Buffer.from([1, 0, 0, 0])).int()).eq(1) - expect(TlBinaryReader.manual(Buffer.from([1, 2, 3, 4])).int()).eq( - 67305985, - ) - expect( - new TlBinaryReader({}, Buffer.from([0xff, 0xff, 0xff, 0xff])).int(), - ).eq(-1) + expect(TlBinaryReader.manual(Buffer.from([1, 2, 3, 4])).int()).eq(67305985) + expect(new TlBinaryReader({}, Buffer.from([0xff, 0xff, 0xff, 0xff])).int()).eq(-1) }) it('should read uint32', () => { expect(TlBinaryReader.manual(Buffer.from([0, 0, 0, 0])).uint()).eq(0) expect(TlBinaryReader.manual(Buffer.from([1, 0, 0, 0])).uint()).eq(1) - expect(TlBinaryReader.manual(Buffer.from([1, 2, 3, 4])).uint()).eq( - 67305985, - ) - expect( - new TlBinaryReader({}, Buffer.from([0xff, 0xff, 0xff, 0xff])).uint(), - ).eq(4294967295) + expect(TlBinaryReader.manual(Buffer.from([1, 2, 3, 4])).uint()).eq(67305985) + expect(new TlBinaryReader({}, Buffer.from([0xff, 0xff, 0xff, 0xff])).uint()).eq(4294967295) }) it('should read int53', () => { - expect( - TlBinaryReader.manual(Buffer.from([0, 0, 0, 0, 0, 0, 0, 0])).int53(), - ).eq(0) - expect( - TlBinaryReader.manual(Buffer.from([1, 0, 0, 0, 0, 0, 0, 0])).int53(), - ).eq(1) - expect( - TlBinaryReader.manual(Buffer.from([1, 2, 3, 4, 0, 0, 0, 0])).int53(), - ).eq(67305985) - expect( - TlBinaryReader.manual(Buffer.from([1, 0, 1, 0, 1, 0, 1, 0])).int53(), - ).eq(281479271743489) - expect( - new TlBinaryReader( - {}, - Buffer.from([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), - ).int53(), - ).eq(-1) + expect(TlBinaryReader.manual(Buffer.from([0, 0, 0, 0, 0, 0, 0, 0])).int53()).eq(0) + expect(TlBinaryReader.manual(Buffer.from([1, 0, 0, 0, 0, 0, 0, 0])).int53()).eq(1) + expect(TlBinaryReader.manual(Buffer.from([1, 2, 3, 4, 0, 0, 0, 0])).int53()).eq(67305985) + expect(TlBinaryReader.manual(Buffer.from([1, 0, 1, 0, 1, 0, 1, 0])).int53()).eq(281479271743489) + expect(new TlBinaryReader({}, Buffer.from([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])).int53()).eq(-1) }) it('should read long', () => { expect( - new TlBinaryReader( - {}, - Buffer.from([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]), - ) - .long() - .toString(), + new TlBinaryReader({}, Buffer.from([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])).long().toString(), ).eq('-1') expect( - new TlBinaryReader( - {}, - Buffer.from([0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78]), - ) - .long() - .toString(), + new TlBinaryReader({}, Buffer.from([0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78])).long().toString(), ).eq('8671175386481439762') expect( - new TlBinaryReader( - {}, - Buffer.from([0x15, 0xc4, 0x15, 0xb5, 0xc4, 0x1c, 0x03, 0xa3]), - ) - .long() - .toString(), + new TlBinaryReader({}, Buffer.from([0x15, 0xc4, 0x15, 0xb5, 0xc4, 0x1c, 0x03, 0xa3])).long().toString(), ).eq('-6700480189419895787') }) it('should read float', () => { - expect( - TlBinaryReader.manual(Buffer.from([0, 0, 0x80, 0x3f])).float(), - ).closeTo(1, 0.001) - expect( - new TlBinaryReader( - {}, - Buffer.from([0xb6, 0xf3, 0x9d, 0x3f]), - ).float(), - ).closeTo(1.234, 0.001) - expect( - new TlBinaryReader( - {}, - Buffer.from([0xfa, 0x7e, 0x2a, 0x3f]), - ).float(), - ).closeTo(0.666, 0.001) + expect(TlBinaryReader.manual(Buffer.from([0, 0, 0x80, 0x3f])).float()).closeTo(1, 0.001) + expect(new TlBinaryReader({}, Buffer.from([0xb6, 0xf3, 0x9d, 0x3f])).float()).closeTo(1.234, 0.001) + expect(new TlBinaryReader({}, Buffer.from([0xfa, 0x7e, 0x2a, 0x3f])).float()).closeTo(0.666, 0.001) }) it('should read double', () => { - expect( - new TlBinaryReader( - {}, - Buffer.from([0, 0, 0, 0, 0, 0, 0xf0, 0x3f]), - ).double(), - ).closeTo(1, 0.001) - expect( - new TlBinaryReader( - {}, - Buffer.from([0, 0, 0, 0, 0, 0, 0x25, 0x40]), - ).double(), - ).closeTo(10.5, 0.001) - expect( - new TlBinaryReader( - {}, - Buffer.from([0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0x21, 0x40]), - ).double(), - ).closeTo(8.8, 0.001) + expect(new TlBinaryReader({}, Buffer.from([0, 0, 0, 0, 0, 0, 0xf0, 0x3f])).double()).closeTo(1, 0.001) + expect(new TlBinaryReader({}, Buffer.from([0, 0, 0, 0, 0, 0, 0x25, 0x40])).double()).closeTo(10.5, 0.001) + expect(new TlBinaryReader({}, Buffer.from([0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0x21, 0x40])).double()).closeTo( + 8.8, + 0.001, + ) }) it('should read raw bytes', () => { - expect([ - ...TlBinaryReader.manual(Buffer.from([1, 2, 3, 4])).raw(2), - ]).eql([1, 2]) - expect([...TlBinaryReader.manual(Buffer.from([1, 2, 3, 4])).raw()]).eql( - [1, 2, 3, 4], - ) - expect([ - ...TlBinaryReader.manual(Buffer.from([1, 2, 3, 4])).raw(0), - ]).eql([]) + expect([...TlBinaryReader.manual(Buffer.from([1, 2, 3, 4])).raw(2)]).eql([1, 2]) + expect([...TlBinaryReader.manual(Buffer.from([1, 2, 3, 4])).raw()]).eql([1, 2, 3, 4]) + expect([...TlBinaryReader.manual(Buffer.from([1, 2, 3, 4])).raw(0)]).eql([]) }) it('should move cursor', () => { - const reader = new TlBinaryReader( - {}, - Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]), - ) + const reader = new TlBinaryReader({}, Buffer.from([1, 2, 3, 4, 5, 6, 7, 8])) reader.int() expect(reader.pos).eq(4) @@ -164,15 +95,10 @@ describe('TlBinaryReader', () => { }) it('should read tg-encoded bytes', () => { - expect([ - ...TlBinaryReader.manual(Buffer.from([1, 2, 3, 4])).bytes(), - ]).eql([2]) + expect([...TlBinaryReader.manual(Buffer.from([1, 2, 3, 4])).bytes()]).eql([2]) const random250bytes = randomBytes(250) - let reader = new TlBinaryReader( - {}, - Buffer.from([250, ...random250bytes, 0, 0, 0, 0, 0]), - ) + let reader = new TlBinaryReader({}, Buffer.from([250, ...random250bytes, 0, 0, 0, 0, 0])) expect([...reader.bytes()]).eql([...random250bytes]) expect(reader.pos).eq(252) @@ -316,14 +242,9 @@ describe('TlBinaryReader', () => { const expected = { nonce: Buffer.from('3E0549828CCA27E966B301A48FECE2FC', 'hex'), - serverNonce: Buffer.from( - 'A5CF4D33F4A11EA877BA4AA573907330', - 'hex', - ), + serverNonce: Buffer.from('A5CF4D33F4A11EA877BA4AA573907330', 'hex'), pq: Buffer.from('17ED48941A08F981', 'hex'), - serverPublicKeyFingerprints: [ - Long.fromString('c3b42b026ce86b21', false, 16), - ], + serverPublicKeyFingerprints: [Long.fromString('c3b42b026ce86b21', false, 16)], } const r = new TlBinaryReader(map, Buffer.from(input, 'hex')) @@ -335,9 +256,7 @@ describe('TlBinaryReader', () => { const obj = r.object() as any expect(obj._).eq('mt_resPQ') expect(obj.nonce.toString('hex')).eq(expected.nonce.toString('hex')) - expect(obj.serverNonce.toString('hex')).eq( - expected.serverNonce.toString('hex'), - ) + expect(obj.serverNonce.toString('hex')).eq(expected.serverNonce.toString('hex')) expect(obj.pq.toString('hex')).eq(expected.pq.toString('hex')) expect(obj.serverPublicKeyFingerprints.length).eq(1) expect(obj.serverPublicKeyFingerprints[0].toString(16)).eq( diff --git a/packages/tl-runtime/tests/binary-writer.spec.ts b/packages/tl-runtime/tests/binary-writer.spec.ts index 6c4a9564..4a5b5b2e 100644 --- a/packages/tl-runtime/tests/binary-writer.spec.ts +++ b/packages/tl-runtime/tests/binary-writer.spec.ts @@ -7,11 +7,7 @@ import { describe, it } from 'mocha' import { TlBinaryWriter, TlSerializationCounter, TlWriterMap } from '../src' describe('TlBinaryWriter', () => { - const testSingleMethod = ( - size: number, - fn: (w: TlBinaryWriter) => void, - map?: TlWriterMap, - ): string => { + const testSingleMethod = (size: number, fn: (w: TlBinaryWriter) => void, map?: TlWriterMap): string => { const w = TlBinaryWriter.alloc(map, size) fn(w) expect(w.pos).eq(size) @@ -36,29 +32,15 @@ describe('TlBinaryWriter', () => { it('should write int53', () => { expect(testSingleMethod(8, (w) => w.int53(0))).eq('0000000000000000') expect(testSingleMethod(8, (w) => w.int53(1))).eq('0100000000000000') - expect(testSingleMethod(8, (w) => w.int53(67305985))).eq( - '0102030400000000', - ) - expect(testSingleMethod(8, (w) => w.int53(281479271743489))).eq( - '0100010001000100', - ) + expect(testSingleMethod(8, (w) => w.int53(67305985))).eq('0102030400000000') + expect(testSingleMethod(8, (w) => w.int53(281479271743489))).eq('0100010001000100') expect(testSingleMethod(8, (w) => w.int53(-1))).eq('ffffffffffffffff') }) it('should write long', () => { - expect(testSingleMethod(8, (w) => w.long(Long.NEG_ONE))).eq( - 'ffffffffffffffff', - ) - expect( - testSingleMethod(8, (w) => - w.long(Long.fromString('8671175386481439762')), - ), - ).eq('1234567812345678') - expect( - testSingleMethod(8, (w) => - w.long(Long.fromString('-6700480189419895787')), - ), - ).eq('15c415b5c41c03a3') + expect(testSingleMethod(8, (w) => w.long(Long.NEG_ONE))).eq('ffffffffffffffff') + expect(testSingleMethod(8, (w) => w.long(Long.fromString('8671175386481439762')))).eq('1234567812345678') + expect(testSingleMethod(8, (w) => w.long(Long.fromString('-6700480189419895787')))).eq('15c415b5c41c03a3') }) it('should write float', () => { @@ -69,16 +51,12 @@ describe('TlBinaryWriter', () => { it('should write double', () => { expect(testSingleMethod(8, (w) => w.double(1))).eq('000000000000f03f') - expect(testSingleMethod(8, (w) => w.double(10.5))).eq( - '0000000000002540', - ) + expect(testSingleMethod(8, (w) => w.double(10.5))).eq('0000000000002540') expect(testSingleMethod(8, (w) => w.double(8.8))).eq('9a99999999992140') }) it('should write raw bytes', () => { - expect( - testSingleMethod(5, (w) => w.raw(Buffer.from([4, 3, 5, 1, 1]))), - ).eq('0403050101') + expect(testSingleMethod(5, (w) => w.raw(Buffer.from([4, 3, 5, 1, 1])))).eq('0403050101') }) it('should write tg-encoded boolean', () => { @@ -87,26 +65,18 @@ describe('TlBinaryWriter', () => { }) it('should write tg-encoded bytes', () => { - expect(testSingleMethod(4, (w) => w.bytes(Buffer.from([1, 2, 3])))).eq( - '03010203', - ) - expect( - testSingleMethod(8, (w) => w.bytes(Buffer.from([1, 2, 3, 4]))), - ).eq('0401020304000000') + expect(testSingleMethod(4, (w) => w.bytes(Buffer.from([1, 2, 3])))).eq('03010203') + expect(testSingleMethod(8, (w) => w.bytes(Buffer.from([1, 2, 3, 4])))).eq('0401020304000000') const random250bytes = randomBytes(250) - expect(testSingleMethod(252, (w) => w.bytes(random250bytes))).eq( - 'fa' + random250bytes.toString('hex') + '00', - ) + expect(testSingleMethod(252, (w) => w.bytes(random250bytes))).eq('fa' + random250bytes.toString('hex') + '00') const random1000bytes = randomBytes(1000) const buffer = Buffer.alloc(1004) buffer[0] = 254 buffer.writeIntLE(1000, 1, 3) buffer.set(random1000bytes, 4) - expect(testSingleMethod(1004, (w) => w.bytes(random1000bytes))).eq( - buffer.toString('hex'), - ) + expect(testSingleMethod(1004, (w) => w.bytes(random1000bytes))).eq(buffer.toString('hex')) }) const stubObjectsMap: TlWriterMap = { @@ -188,9 +158,7 @@ describe('TlBinaryWriter', () => { }, stubObjectsMap, ), - ).eq( - '15c4b51c03000000efbeadde01000000addecefadec0adba020000003d0cbfbe15c4b51c020000000100000002000000', - ) + ).eq('15c4b51c03000000efbeadde01000000addecefadec0adba020000003d0cbfbe15c4b51c020000000100000002000000') }) describe('examples from documentation', () => { @@ -202,14 +170,9 @@ describe('TlBinaryWriter', () => { const resPq = { _: 'mt_resPQ', nonce: Buffer.from('3E0549828CCA27E966B301A48FECE2FC', 'hex'), - serverNonce: Buffer.from( - 'A5CF4D33F4A11EA877BA4AA573907330', - 'hex', - ), + serverNonce: Buffer.from('A5CF4D33F4A11EA877BA4AA573907330', 'hex'), pq: Buffer.from('17ED48941A08F981', 'hex'), - serverPublicKeyFingerprints: [ - Long.fromString('c3b42b026ce86b21', 16), - ], + serverPublicKeyFingerprints: [Long.fromString('c3b42b026ce86b21', 16)], } const map: TlWriterMap = { diff --git a/packages/tl-utils/src/calculator.ts b/packages/tl-utils/src/calculator.ts index a69bb1b3..c16f7d77 100644 --- a/packages/tl-utils/src/calculator.ts +++ b/packages/tl-utils/src/calculator.ts @@ -14,9 +14,7 @@ const PRIMITIVES_SIZES: Record = { '#': 4, } -export function calculateStaticSizes( - entries: TlEntry[], -): Record { +export function calculateStaticSizes(entries: TlEntry[]): Record { const staticSizes: Record = {} const unionSizes: Record> = {} let changedInLastIteration = true @@ -50,10 +48,7 @@ export function calculateStaticSizes( return null } - if ( - arg.typeModifiers?.isVector || - arg.typeModifiers?.isBareVector - ) { + if (arg.typeModifiers?.isVector || arg.typeModifiers?.isBareVector) { // cant be static sized return null } diff --git a/packages/tl-utils/src/codegen/errors.ts b/packages/tl-utils/src/codegen/errors.ts index e853910b..7b434cf6 100644 --- a/packages/tl-utils/src/codegen/errors.ts +++ b/packages/tl-utils/src/codegen/errors.ts @@ -54,10 +54,7 @@ export class RpcError extends Error { } `.trimStart() -const template = ( - str: string, - params: Record, -): string => { +const template = (str: string, params: Record): string => { return str.replace(/{([a-z]+)}/gi, (_, name) => String(params[name] ?? '')) } @@ -103,10 +100,7 @@ function placeholderType(_name: string): string { * @param exports Prefix for exports object * @returns Tuple containing `[ts, js]` code */ -export function generateCodeForErrors( - errors: TlErrors, - exports = 'exports.', -): [string, string] { +export function generateCodeForErrors(errors: TlErrors, exports = 'exports.'): [string, string] { const descriptionsMap: Record = {} let texts = '' let argMap = '' @@ -131,16 +125,10 @@ export function generateCodeForErrors( if (placeholders.length) { const placeholderTypes = placeholders.map(placeholderType) argMap += - ` '${name}': { ` + - placeholders - .map((it, i) => `${it}: ${placeholderTypes[i]}`) - .join(', ') + - ' },\n' + ` '${name}': { ` + placeholders.map((it, i) => `${it}: ${placeholderTypes[i]}`).join(', ') + ' },\n' const regex = name.replace('%d', '(\\d+)') - const setters = placeholders - .map((it, i) => `err.${it} = parseInt(match[${i + 1}])`) - .join('; ') + const setters = placeholders.map((it, i) => `err.${it} = parseInt(match[${i + 1}])`).join('; ') matchers += ` if ((match=obj.errorMessage.match(/^${regex}$/))!=null){ err.text = '${name}'; ${setters} }\n` } } @@ -150,10 +138,7 @@ export function generateCodeForErrors( template(TEMPLATE_JS, { exports, statics: staticsJs, - descriptionsMap: JSON.stringify(descriptionsMap).replace( - /'/g, - "\\'", - ), + descriptionsMap: JSON.stringify(descriptionsMap).replace(/'/g, "\\'"), matchers, }), ] diff --git a/packages/tl-utils/src/codegen/reader.ts b/packages/tl-utils/src/codegen/reader.ts index 5b8a16e0..de202000 100644 --- a/packages/tl-utils/src/codegen/reader.ts +++ b/packages/tl-utils/src/codegen/reader.ts @@ -45,10 +45,7 @@ const DEFAULT_OPTIONS: ReaderCodegenOptions = { * @param params Options * @returns Code as a writers map entry */ -export function generateReaderCodeForTlEntry( - entry: TlEntry, - params = DEFAULT_OPTIONS, -): string { +export function generateReaderCodeForTlEntry(entry: TlEntry, params = DEFAULT_OPTIONS): string { const { variableName, includeFlags } = { ...DEFAULT_OPTIONS, ...params } if (entry.id === 0) entry.id = computeConstructorIdFromEntry(entry) @@ -94,9 +91,7 @@ export function generateReaderCodeForTlEntry( const bitIndex = parseInt(s[1]) if (!(fieldName in flagsFields)) { - throw new Error( - `Invalid predicate: ${predicate} - unknown field (in ${entry.name})`, - ) + throw new Error(`Invalid predicate: ${predicate} - unknown field (in ${entry.name})`) } if (isNaN(bitIndex) || bitIndex < 0 || bitIndex > 32) { throw new Error(`Invalid predicate: ${predicate} - invalid bit`) @@ -132,14 +127,11 @@ export function generateReaderCodeForTlEntry( } let reader = `r.${type}` - const isBare = - arg.typeModifiers?.isBareType || arg.typeModifiers?.isBareUnion + const isBare = arg.typeModifiers?.isBareType || arg.typeModifiers?.isBareUnion if (isBare) { if (!arg.typeModifiers?.constructorId) { - throw new Error( - `Cannot generate reader for ${entry.name}#${arg.name} - no constructor id referenced`, - ) + throw new Error(`Cannot generate reader for ${entry.name}#${arg.name} - no constructor id referenced`) } reader = `${variableName}[${arg.typeModifiers.constructorId}]` @@ -175,10 +167,7 @@ export function generateReaderCodeForTlEntry( * @param entries Entries to generate reader for * @param params Codegen options */ -export function generateReaderCodeForTlEntries( - entries: TlEntry[], - params = DEFAULT_OPTIONS, -): string { +export function generateReaderCodeForTlEntries(entries: TlEntry[], params = DEFAULT_OPTIONS): string { const { variableName, includeMethods } = { ...DEFAULT_OPTIONS, ...params } let ret = `var ${variableName}={\n` @@ -189,20 +178,14 @@ export function generateReaderCodeForTlEntries( }) const usedInBareVector: Record = {} - ret.replace( - new RegExp(`(?<=r\\.vector\\(${variableName}\\[)(\\d+)(?=])`, 'g'), - (_, id: string) => { - usedInBareVector[id] = 1 + ret.replace(new RegExp(`(?<=r\\.vector\\(${variableName}\\[)(\\d+)(?=])`, 'g'), (_, id: string) => { + usedInBareVector[id] = 1 - return _ - }, - ) + return _ + }) for (const id of Object.keys(usedInBareVector)) { - ret = ret.replace( - new RegExp(`(?<=^${id}:function\\()r(?=\\))`, 'gm'), - 'r=this', - ) + ret = ret.replace(new RegExp(`(?<=^${id}:function\\()r(?=\\))`, 'gm'), 'r=this') } if (params.includeMethodResults) { @@ -213,9 +196,7 @@ export function generateReaderCodeForTlEntries( const pre = `'${entry.name}':function(r){return ` - const isVector = - entry.typeModifiers?.isVector || - entry.typeModifiers?.isBareVector + const isVector = entry.typeModifiers?.isVector || entry.typeModifiers?.isBareVector const post = entry.typeModifiers?.isBareVector ? ',1' : '' if (entry.type in TL_PRIMITIVES) { diff --git a/packages/tl-utils/src/codegen/types.ts b/packages/tl-utils/src/codegen/types.ts index 6fbb1808..16c1a0f8 100644 --- a/packages/tl-utils/src/codegen/types.ts +++ b/packages/tl-utils/src/codegen/types.ts @@ -103,11 +103,10 @@ export function generateTypescriptDefinitionsForTlEntry( if (entry.kind === 'method' && !entry.generics) { if (comment) comment += '\n\n' - comment += `RPC method returns ${fullTypeName( - entry.type, - baseNamespace, - { link: true, typeModifiers: entry.typeModifiers }, - )}` + comment += `RPC method returns ${fullTypeName(entry.type, baseNamespace, { + link: true, + typeModifiers: entry.typeModifiers, + })}` if (errors) { if (errors.userOnly[entry.name]) { @@ -115,9 +114,7 @@ export function generateTypescriptDefinitionsForTlEntry( } if (errors.throws[entry.name]) { - comment += - '\n\nThis method *may* throw one of these errors: ' + - errors.throws[entry.name].join(', ') + comment += '\n\nThis method *may* throw one of these errors: ' + errors.throws[entry.name].join(', ') } } } @@ -129,10 +126,7 @@ export function generateTypescriptDefinitionsForTlEntry( if (entry.generics?.length) { genericsString = '<' entry.generics.forEach((it, idx) => { - const tsType = - it.type === 'Type' ? - 'tl.TlObject' : - fullTypeName(it.type, baseNamespace) + const tsType = it.type === 'Type' ? 'tl.TlObject' : fullTypeName(it.type, baseNamespace) genericsIndex[it.name] = 1 if (idx !== 0) genericsString += ', ' @@ -141,9 +135,7 @@ export function generateTypescriptDefinitionsForTlEntry( genericsString += '>' } - ret += `interface ${entryFullTypeName(entry)}${genericsString} {\n _: '${ - entry.name - }';\n` + ret += `interface ${entryFullTypeName(entry)}${genericsString} {\n _: '${entry.name}';\n` entry.arguments.forEach((arg) => { if (arg.type === '#') { @@ -238,14 +230,8 @@ export function generateTypescriptDefinitionsForTlSchema( namespace = 'tl', errors?: TlErrors, ): [string, string] { - let ts = PRELUDE.replace('$NS$', namespace).replace( - '$LAYER$', - String(layer), - ) - let js = PRELUDE_JS.replace('$NS$', namespace).replace( - '$LAYER$', - String(layer), - ) + let ts = PRELUDE.replace('$NS$', namespace).replace('$LAYER$', String(layer)) + let js = PRELUDE_JS.replace('$NS$', namespace).replace('$LAYER$', String(layer)) if (errors) { // ts += '\n namespace errors {\n' @@ -277,14 +263,7 @@ export function generateTypescriptDefinitionsForTlSchema( unions[entry.type] = 1 } - ts += - indent( - indentSize, - generateTypescriptDefinitionsForTlEntry( - entry, - namespace + '.', - ), - ) + '\n' + ts += indent(indentSize, generateTypescriptDefinitionsForTlEntry(entry, namespace + '.')) + '\n' }) ts += indent(indentSize, 'interface RpcCallReturn') @@ -317,10 +296,7 @@ export function generateTypescriptDefinitionsForTlSchema( const g = entry.generics[i] if (g.name === entry.type) { - type = - g.type === 'Type' ? - 'any' : - fullTypeName(g.type, namespace + '.') + type = g.type === 'Type' ? 'any' : fullTypeName(g.type, namespace + '.') break } } @@ -358,11 +334,7 @@ export function generateTypescriptDefinitionsForTlSchema( ts += '\n' - ts += - indent( - indentSize, - `function isAny${typeWithoutNs}(o: object): o is ${typeName}`, - ) + '\n' + ts += indent(indentSize, `function isAny${typeWithoutNs}(o: object): o is ${typeName}`) + '\n' js += `ns.isAny${typeWithoutNs} = _isAny('${name}');\n` } @@ -384,12 +356,7 @@ export function generateTypescriptDefinitionsForTlSchema( } const entry = schema.methods[name] - ts += - indent( - 8, - '| ' + - fullTypeName(entry.name, namespace + '.', { method: true }), - ) + '\n' + ts += indent(8, '| ' + fullTypeName(entry.name, namespace + '.', { method: true })) + '\n' } ts += '\n' + indent(4, 'type TlObject =') + '\n' diff --git a/packages/tl-utils/src/codegen/utils.ts b/packages/tl-utils/src/codegen/utils.ts index 8705c0dc..4b79e619 100644 --- a/packages/tl-utils/src/codegen/utils.ts +++ b/packages/tl-utils/src/codegen/utils.ts @@ -12,8 +12,7 @@ export const snakeToCamel = (s: string): string => { * Transform camelCase string to PascalCase string * @param s camelCase string */ -export const camelToPascal = (s: string): string => - s[0].toUpperCase() + s.substring(1) +export const camelToPascal = (s: string): string => s[0].toUpperCase() + s.substring(1) /** * Format a string as a JS documentation comment diff --git a/packages/tl-utils/src/codegen/writer.ts b/packages/tl-utils/src/codegen/writer.ts index 2143c0fc..8cc76205 100644 --- a/packages/tl-utils/src/codegen/writer.ts +++ b/packages/tl-utils/src/codegen/writer.ts @@ -55,10 +55,7 @@ const TL_WRITER_PRELUDE = * @param params Options * @returns Code as a readers map entry */ -export function generateWriterCodeForTlEntry( - entry: TlEntry, - params = DEFAULT_OPTIONS, -): string { +export function generateWriterCodeForTlEntry(entry: TlEntry, params = DEFAULT_OPTIONS): string { const { bare, includeFlags, variableName } = { ...DEFAULT_OPTIONS, ...params, @@ -68,9 +65,7 @@ export function generateWriterCodeForTlEntry( const name = bare ? entry.id : `'${entry.name}'` const defaultWriter = bare ? '=this' : '' - let ret = `${name}:function(w${defaultWriter}${ - entry.arguments.length ? ',v' : '' - }){` + let ret = `${name}:function(w${defaultWriter}${entry.arguments.length ? ',v' : ''}){` if (!bare) ret += `w.uint(${entry.id});` @@ -94,19 +89,14 @@ export function generateWriterCodeForTlEntry( const bitIndex = parseInt(s[1]) if (isNaN(bitIndex) || bitIndex < 0 || bitIndex > 32) { - throw new Error( - `Invalid predicate: ${predicate} - invalid bit`, - ) + throw new Error(`Invalid predicate: ${predicate} - invalid bit`) } const action = `${arg.name}|=${1 << bitIndex};` if (arg1.type === 'true') { ret += `if(v.${arg1Name}===true)${action}` - } else if ( - arg1.typeModifiers?.isVector || - arg1.typeModifiers?.isBareVector - ) { + } else if (arg1.typeModifiers?.isVector || arg1.typeModifiers?.isBareVector) { ret += `var _${arg1Name}=v.${arg1Name}&&v.${arg1Name}.length;if(_${arg1Name})${action}` } else { ret += `var _${arg1Name}=v.${arg1Name}!==undefined;if(_${arg1Name})${action}` @@ -140,14 +130,11 @@ export function generateWriterCodeForTlEntry( } let writer = `w.${type}` - const isBare = - arg.typeModifiers?.isBareType || arg.typeModifiers?.isBareUnion + const isBare = arg.typeModifiers?.isBareType || arg.typeModifiers?.isBareUnion if (isBare) { if (!arg.typeModifiers?.constructorId) { - throw new Error( - `Cannot generate writer for ${entry.name}#${arg.name} - no constructor id referenced`, - ) + throw new Error(`Cannot generate writer for ${entry.name}#${arg.name} - no constructor id referenced`) } writer = `${variableName}._bare[${arg.typeModifiers.constructorId}]` @@ -171,10 +158,7 @@ export function generateWriterCodeForTlEntry( * @param entries Entries to generate writers for * @param params Codegen options */ -export function generateWriterCodeForTlEntries( - entries: TlEntry[], - params = DEFAULT_OPTIONS, -): string { +export function generateWriterCodeForTlEntries(entries: TlEntry[], params = DEFAULT_OPTIONS): string { const { includePrelude, variableName, includeStaticSizes } = { ...DEFAULT_OPTIONS, ...params, diff --git a/packages/tl-utils/src/ctor-id.ts b/packages/tl-utils/src/ctor-id.ts index 262fda8a..e2dc6220 100644 --- a/packages/tl-utils/src/ctor-id.ts +++ b/packages/tl-utils/src/ctor-id.ts @@ -10,9 +10,7 @@ import { TlEntry } from './types' * @param line Line containing TL entry definition */ export function computeConstructorIdFromString(line: string): number { - return computeConstructorIdFromEntry( - parseTlToEntries(line, { forIdComputation: true })[0], - ) + return computeConstructorIdFromEntry(parseTlToEntries(line, { forIdComputation: true })[0]) } /** diff --git a/packages/tl-utils/src/diff.ts b/packages/tl-utils/src/diff.ts index 02b7af94..1a259508 100644 --- a/packages/tl-utils/src/diff.ts +++ b/packages/tl-utils/src/diff.ts @@ -1,12 +1,5 @@ import { computeConstructorIdFromEntry } from './ctor-id' -import { - TlArgument, - TlArgumentDiff, - TlEntry, - TlEntryDiff, - TlFullSchema, - TlSchemaDiff, -} from './types' +import { TlArgument, TlArgumentDiff, TlEntry, TlEntryDiff, TlFullSchema, TlSchemaDiff } from './types' import { stringifyArgumentType } from './utils' /** @@ -15,10 +8,7 @@ import { stringifyArgumentType } from './utils' * @param a Entry A (field `old` in diff) * @param b Entry B (field `new` in diff) */ -export function generateTlEntriesDifference( - a: TlEntry, - b: TlEntry, -): TlEntryDiff { +export function generateTlEntriesDifference(a: TlEntry, b: TlEntry): TlEntryDiff { if (a.kind !== b.kind || a.name !== b.name) { throw new Error('Incompatible entries') } @@ -51,9 +41,7 @@ export function generateTlEntriesDifference( if ( !a.generics !== !b.generics || - (a.generics && - b.generics && - JSON.stringify(a.generics) !== JSON.stringify(b.generics)) + (a.generics && b.generics && JSON.stringify(a.generics) !== JSON.stringify(b.generics)) ) { diff.generics = { old: a.generics, @@ -91,10 +79,7 @@ export function generateTlEntriesDifference( } const argStr = stringifyArgumentType(arg.type, arg.typeModifiers) - const oldArgStr = stringifyArgumentType( - oldArg.type, - oldArg.typeModifiers, - ) + const oldArgStr = stringifyArgumentType(oldArg.type, oldArg.typeModifiers) if (argStr !== oldArgStr) { diff.type = { @@ -121,11 +106,7 @@ export function generateTlEntriesDifference( } }) - if ( - argsDiff.added.length || - argsDiff.removed.length || - argsDiff.modified.length - ) { + if (argsDiff.added.length || argsDiff.removed.length || argsDiff.modified.length) { diff.arguments = argsDiff } @@ -138,10 +119,7 @@ export function generateTlEntriesDifference( * @param a Entry A (field `old` in diff) * @param b Entry B (field `new` in diff) */ -export function generateTlSchemasDifference( - a: TlFullSchema, - b: TlFullSchema, -): TlSchemaDiff { +export function generateTlSchemasDifference(a: TlFullSchema, b: TlFullSchema): TlSchemaDiff { // schemas already contain indexes, so we don't need to make our own const diff: TlSchemaDiff = { @@ -162,10 +140,7 @@ export function generateTlSchemasDifference( }, } - const unionDiffIndex: Record< - string, - TlSchemaDiff['unions']['modified'][number] - > = {} + const unionDiffIndex: Record = {} const unionDiffIndex2: Record = {} a.entries.forEach((entry) => { diff --git a/packages/tl-utils/src/merge.ts b/packages/tl-utils/src/merge.ts index 61a3df10..bef6147c 100644 --- a/packages/tl-utils/src/merge.ts +++ b/packages/tl-utils/src/merge.ts @@ -83,8 +83,7 @@ export function mergeTlEntries(entries: TlEntry[]): TlEntry | string { // we also need to make sure we put it *after* the respective flags field - const flagsField = - entryArgument.typeModifiers.predicate.split('.')[0] + const flagsField = entryArgument.typeModifiers.predicate.split('.')[0] const targetIdx = flagsLastIndex[flagsField] // targetIdx *must* exist, otherwise ids wouldn't match @@ -126,7 +125,7 @@ export async function mergeTlSchemas( schemas: TlFullSchema[], onConflict: ( options: (TlEntry | undefined)[], - reason: string + reason: string, ) => TlEntry | undefined | Promise, ): Promise { const result: TlFullSchema = { @@ -147,10 +146,7 @@ export async function mergeTlSchemas( const kind = entry.kind === 'class' ? 'classes' : 'methods' const index = result[kind] - const conflictIndex = - entry.kind === 'class' ? - resolvedConflictsClasses : - resolvedConflictsMethods + const conflictIndex = entry.kind === 'class' ? resolvedConflictsClasses : resolvedConflictsMethods if (entry.name in conflictIndex) { // this entry was manually processed by user after a conflict @@ -170,9 +166,7 @@ export async function mergeTlSchemas( if (typeof merged === 'string') { // merge conflict // find all candidates from all schemas and let the user decide - const candidates = schemas.map( - (schema) => schema[kind][entry.name], - ) + const candidates = schemas.map((schema) => schema[kind][entry.name]) const chosen = await onConflict(candidates, merged) diff --git a/packages/tl-utils/src/parse.ts b/packages/tl-utils/src/parse.ts index a48df9e3..f2e2ace1 100644 --- a/packages/tl-utils/src/parse.ts +++ b/packages/tl-utils/src/parse.ts @@ -2,8 +2,7 @@ import { computeConstructorIdFromString } from './ctor-id' import { TL_PRIMITIVES, TlArgument, TlEntry } from './types' import { parseArgumentType, parseTdlibStyleComment } from './utils' -const SINGLE_REGEX = - /^(.+?)(?:#([0-9a-f]{1,8}))?(?: \?)?(?: {(.+?:.+?)})? ((?:.+? )*)= (.+);$/ +const SINGLE_REGEX = /^(.+?)(?:#([0-9a-f]{1,8}))?(?: \?)?(?: {(.+?:.+?)})? ((?:.+? )*)= (.+);$/ /** * Parse TL schema into a list of entries. diff --git a/packages/tl-utils/src/patch.ts b/packages/tl-utils/src/patch.ts index 99093650..2b6980d9 100644 --- a/packages/tl-utils/src/patch.ts +++ b/packages/tl-utils/src/patch.ts @@ -40,12 +40,8 @@ export function patchRuntimeTlSchema( includePrelude: true, }) - const newReaders = evalForResult( - readersCode.replace('var _=', 'return'), - ) - const newWriters = evalForResult( - writersCode.replace('var _=', 'return'), - ) + const newReaders = evalForResult(readersCode.replace('var _=', 'return')) + const newWriters = evalForResult(writersCode.replace('var _=', 'return')) return { readerMap: { diff --git a/packages/tl-utils/src/schema.ts b/packages/tl-utils/src/schema.ts index 998f3242..481d0d6f 100644 --- a/packages/tl-utils/src/schema.ts +++ b/packages/tl-utils/src/schema.ts @@ -2,8 +2,7 @@ import { computeConstructorIdFromEntry } from './ctor-id' import { writeTlEntryToString } from './stringify' import { TlEntry, TlFullSchema } from './types' -const replaceNewlineInComment = (s: string): string => - s.replace(/\n/g, '\n//- ') +const replaceNewlineInComment = (s: string): string => s.replace(/\n/g, '\n//- ') /** * Parse TL entries into a full schema object @@ -99,9 +98,7 @@ boolTrue#997275b5 = Bool; if (entry.comment) { if (params?.tdlibComments) { - lines.push( - `// @description ${replaceNewlineInComment(entry.comment)}`, - ) + lines.push(`// @description ${replaceNewlineInComment(entry.comment)}`) } else { lines.push(`// ${replaceNewlineInComment(entry.comment)}`) } @@ -110,11 +107,7 @@ boolTrue#997275b5 = Bool; if (params?.tdlibComments) { entry.arguments.forEach((arg) => { if (arg.comment) { - lines.push( - `// @${arg.name} ${replaceNewlineInComment( - arg.comment, - )}`, - ) + lines.push(`// @${arg.name} ${replaceNewlineInComment(arg.comment)}`) } }) } diff --git a/packages/tl-utils/src/stringify.ts b/packages/tl-utils/src/stringify.ts index 0a91629a..f3ddd079 100644 --- a/packages/tl-utils/src/stringify.ts +++ b/packages/tl-utils/src/stringify.ts @@ -17,10 +17,7 @@ function normalizeType(s: string): string { * Whether to generate definition for constructor ID computation * (it has slightly different syntax, will not contain `true` flags, etc.) */ -export function writeTlEntryToString( - entry: TlEntry, - forIdComputation = false, -): string { +export function writeTlEntryToString(entry: TlEntry, forIdComputation = false): string { let str = entry.name if (!forIdComputation && entry.id) { @@ -40,11 +37,7 @@ export function writeTlEntryToString( } for (const arg of entry.arguments) { - if ( - forIdComputation && - arg.typeModifiers?.predicate && - arg.type === 'true' - ) { + if (forIdComputation && arg.typeModifiers?.predicate && arg.type === 'true') { continue } @@ -62,9 +55,7 @@ export function writeTlEntryToString( if (forIdComputation) { str += '= ' + normalizeType(entry.type) } else { - const type = entry.typeModifiers ? - stringifyArgumentType(entry.type, entry.typeModifiers) : - entry.type + const type = entry.typeModifiers ? stringifyArgumentType(entry.type, entry.typeModifiers) : entry.type str += '= ' + type + ';' } diff --git a/packages/tl-utils/src/utils.ts b/packages/tl-utils/src/utils.ts index d02e7ce7..c98fad73 100644 --- a/packages/tl-utils/src/utils.ts +++ b/packages/tl-utils/src/utils.ts @@ -45,9 +45,7 @@ export function parseTdlibStyleComment(str: string): Record { * @param entries Entries to group * @returns Mapping of namespace to entries. Base namespace is `''` (empty string). */ -export function groupTlEntriesByNamespace( - entries: TlEntry[], -): Record { +export function groupTlEntriesByNamespace(entries: TlEntry[]): Record { const ret: Record = {} entries.forEach((entry) => { @@ -61,10 +59,7 @@ export function groupTlEntriesByNamespace( return ret } -export function stringifyArgumentType( - type: string, - modifiers?: TlTypeModifiers, -) { +export function stringifyArgumentType(type: string, modifiers?: TlTypeModifiers) { if (!modifiers) return type let ret = type diff --git a/packages/tl-utils/tests/calculator.spec.ts b/packages/tl-utils/tests/calculator.spec.ts index 69bf9fb8..91a976fe 100644 --- a/packages/tl-utils/tests/calculator.spec.ts +++ b/packages/tl-utils/tests/calculator.spec.ts @@ -14,17 +14,15 @@ describe('calculateStaticSizes', () => { }) it('computes for constructors with static parameters', () => { - test( - 'auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;', - { 'auth.exportAuthorization': 8 }, - ) + test('auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;', { + 'auth.exportAuthorization': 8, + }) }) it('correctly skips true fields', () => { - test( - 'help.promoData#8c39793f flags:# proxy:flags.0?true expires:int = help.PromoData;', - { 'help.promoData': 12 }, - ) + test('help.promoData#8c39793f flags:# proxy:flags.0?true expires:int = help.PromoData;', { + 'help.promoData': 12, + }) }) it('correctly skips constructors with predicated fields', () => { @@ -35,17 +33,11 @@ describe('calculateStaticSizes', () => { }) it('correctly skips constructors with non-static fields', () => { - test( - 'help.promoData#8c39793f psa_type:string psa_message:string = help.PromoData;', - {}, - ) + test('help.promoData#8c39793f psa_type:string psa_message:string = help.PromoData;', {}) }) it('correctly skips constructors with vector fields', () => { - test( - 'help.promoData#8c39793f psa_type:Vector = help.PromoData;', - {}, - ) + test('help.promoData#8c39793f psa_type:Vector = help.PromoData;', {}) }) it('correctly handles static-sized children', () => { diff --git a/packages/tl-utils/tests/codegen/reader.spec.ts b/packages/tl-utils/tests/codegen/reader.spec.ts index d735d0ac..c7488ada 100644 --- a/packages/tl-utils/tests/codegen/reader.spec.ts +++ b/packages/tl-utils/tests/codegen/reader.spec.ts @@ -6,16 +6,11 @@ import { generateReaderCodeForTlEntry, parseTlToEntries } from '../../src' describe('generateReaderCodeForTlEntry', () => { const test = (tl: string, ...js: string[]) => { const entry = parseTlToEntries(tl).slice(-1)[0] - expect(generateReaderCodeForTlEntry(entry)).eq( - `${entry.id}:function(r){${js.join('')}},`, - ) + expect(generateReaderCodeForTlEntry(entry)).eq(`${entry.id}:function(r){${js.join('')}},`) } it('generates code for constructors without arguments', () => { - test( - 'topPeerCategoryBotsPM#ab661b5b = TopPeerCategory;', - "return{_:'topPeerCategoryBotsPM'}", - ) + test('topPeerCategoryBotsPM#ab661b5b = TopPeerCategory;', "return{_:'topPeerCategoryBotsPM'}") }) it('generates code for constructors with simple arguments', () => { @@ -140,8 +135,7 @@ describe('generateReaderCodeForTlEntry', () => { it('generates code for bare types', () => { test( - 'message#0949d9dc = Message;\n' + - 'msg_container#73f1f8dc messages:vector<%Message> = MessageContainer;', + 'message#0949d9dc = Message;\n' + 'msg_container#73f1f8dc messages:vector<%Message> = MessageContainer;', 'return{', "_:'msg_container',", 'messages:r.vector(m[155834844],1),', diff --git a/packages/tl-utils/tests/codegen/types.spec.ts b/packages/tl-utils/tests/codegen/types.spec.ts index 1f9f09b3..31a2249a 100644 --- a/packages/tl-utils/tests/codegen/types.spec.ts +++ b/packages/tl-utils/tests/codegen/types.spec.ts @@ -31,12 +31,7 @@ describe('generateTypescriptDefinitionsForTlEntry', () => { }) it('ignores namespace for name', () => { - test( - 'test.test = Test;', - 'interface RawTest {', - " _: 'test.test';", - '}', - ) + test('test.test = Test;', 'interface RawTest {', " _: 'test.test';", '}') }) it('renames non-primitive types', () => { @@ -77,9 +72,7 @@ describe('generateTypescriptDefinitionsForTlEntry', () => { '}', ) test( - '---functions---\n' + - '// This is a test method\n' + - 'test = Test;', + '---functions---\n' + '// This is a test method\n' + 'test = Test;', '/**', ' * This is a test method', ' * ', @@ -93,9 +86,7 @@ describe('generateTypescriptDefinitionsForTlEntry', () => { it('adds tdlib style comments', () => { test( - '// @description This is a test constructor\n' + - '// @field Some field\n' + - 'test field:int = Test;', + '// @description This is a test constructor\n' + '// @field Some field\n' + 'test field:int = Test;', '/**', ' * This is a test constructor', ' */', @@ -140,8 +131,7 @@ describe('generateTypescriptDefinitionsForTlEntry', () => { it('should not break @link tags', () => { test( - '// This is a test constructor with a very long comment {@link whatever} more text\n' + - 'test = Test;', + '// This is a test constructor with a very long comment {@link whatever} more text\n' + 'test = Test;', '/**', ' * This is a test constructor with a very long comment', ' * {@link whatever} more text', @@ -165,21 +155,8 @@ describe('generateTypescriptDefinitionsForTlEntry', () => { it('generates code with raw flags for constructors with flags', () => { const entry = parseTlToEntries('test flags:# flags2:# = Test;')[0] - expect( - generateTypescriptDefinitionsForTlEntry( - entry, - undefined, - undefined, - true, - ), - ).eq( - [ - 'interface RawTest {', - " _: 'test';", - ' flags: number;', - ' flags2: number;', - '}', - ].join('\n'), + expect(generateTypescriptDefinitionsForTlEntry(entry, undefined, undefined, true)).eq( + ['interface RawTest {', " _: 'test';", ' flags: number;', ' flags2: number;', '}'].join('\n'), ) }) }) @@ -189,24 +166,15 @@ describe('generateTypescriptDefinitionsForTlSchema', () => { const entries = parseTlToEntries(tl) const schema = parseFullTlSchema(entries) - let [codeTs, codeJs] = generateTypescriptDefinitionsForTlSchema( - schema, - 0, - ) + let [codeTs, codeJs] = generateTypescriptDefinitionsForTlSchema(schema, 0) // skip prelude - codeTs = codeTs.substring( - codeTs.indexOf('-readonly [P in keyof T]: T[P]') + 37, - codeTs.length - 1, - ) + codeTs = codeTs.substring(codeTs.indexOf('-readonly [P in keyof T]: T[P]') + 37, codeTs.length - 1) // unindent first level codeTs = codeTs.replace(/^ {4}/gm, '') // skip prelude - codeJs = codeJs.substring( - codeJs.indexOf('ns.LAYER = 0;') + 14, - codeJs.length - 15, - ) + codeJs = codeJs.substring(codeJs.indexOf('ns.LAYER = 0;') + 14, codeJs.length - 15) expect(codeTs.trim()).eq(ts.join('\n')) expect(codeJs.trim()).eq(js.join('\n')) @@ -227,10 +195,7 @@ describe('generateTypescriptDefinitionsForTlSchema', () => { 'type TlObject =', ' | tl.RawTest', ], - [ - "ns.isAnyTest = _isAny('Test');", - '_types = JSON.parse(\'{"test":"Test"}\');', - ], + ["ns.isAnyTest = _isAny('Test');", '_types = JSON.parse(\'{"test":"Test"}\');'], ) }) @@ -253,10 +218,7 @@ describe('generateTypescriptDefinitionsForTlSchema', () => { ' | tl.RawTest', ' | tl.RawTest2', ], - [ - "ns.isAnyTest = _isAny('Test');", - '_types = JSON.parse(\'{"test":"Test","test2":"Test"}\');', - ], + ["ns.isAnyTest = _isAny('Test');", '_types = JSON.parse(\'{"test":"Test","test2":"Test"}\');'], ) }) @@ -285,10 +247,7 @@ describe('generateTypescriptDefinitionsForTlSchema', () => { ' | tl.RawTest', ' | tl.RawGetTestRequest', ], - [ - "ns.isAnyTest = _isAny('Test');", - '_types = JSON.parse(\'{"test":"Test"}\');', - ], + ["ns.isAnyTest = _isAny('Test');", '_types = JSON.parse(\'{"test":"Test"}\');'], ) }) diff --git a/packages/tl-utils/tests/codegen/writer.spec.ts b/packages/tl-utils/tests/codegen/writer.spec.ts index 6cb5c044..c90a5f74 100644 --- a/packages/tl-utils/tests/codegen/writer.spec.ts +++ b/packages/tl-utils/tests/codegen/writer.spec.ts @@ -1,19 +1,13 @@ import { expect } from 'chai' import { describe, it } from 'mocha' -import { - generateWriterCodeForTlEntries, - generateWriterCodeForTlEntry, - parseTlToEntries, -} from '../../src' +import { generateWriterCodeForTlEntries, generateWriterCodeForTlEntry, parseTlToEntries } from '../../src' describe('generateWriterCodeForTlEntry', () => { const test = (tl: string, ...js: string[]) => { const entry = parseTlToEntries(tl).slice(-1)[0] expect(generateWriterCodeForTlEntry(entry)).eq( - `'${entry.name}':function(w${ - entry.arguments.length ? ',v' : '' - }){w.uint(${entry.id});${js.join('')}},`, + `'${entry.name}':function(w${entry.arguments.length ? ',v' : ''}){w.uint(${entry.id});${js.join('')}},`, ) } @@ -111,8 +105,7 @@ describe('generateWriterCodeForTlEntry', () => { it('generates code for bare vectors', () => { test( - 'message#0949d9dc = Message;\n' + - 'msg_container#73f1f8dc messages:vector<%Message> = MessageContainer;', + 'message#0949d9dc = Message;\n' + 'msg_container#73f1f8dc messages:vector<%Message> = MessageContainer;', "w.vector(m._bare[155834844],h(v,'messages'),1);", ) test( @@ -129,9 +122,7 @@ describe('generateWriterCodeForTlEntry', () => { 'future_salts#ae500895 salts:vector current:future_salt = FutureSalts;', ) - expect( - generateWriterCodeForTlEntries(entries, { includePrelude: false }), - ).eq( + expect(generateWriterCodeForTlEntries(entries, { includePrelude: false })).eq( ` var m={ 'future_salt':function(w,v){w.uint(155834844);w.bytes(h(v,'salt'));}, diff --git a/packages/tl-utils/tests/ctor-id.spec.ts b/packages/tl-utils/tests/ctor-id.spec.ts index 342d9df3..9075c2e9 100644 --- a/packages/tl-utils/tests/ctor-id.spec.ts +++ b/packages/tl-utils/tests/ctor-id.spec.ts @@ -1,12 +1,7 @@ import { expect } from 'chai' import { describe, it } from 'mocha' -import { - computeConstructorIdFromEntry, - computeConstructorIdFromString, - TlArgument, - TlEntry, -} from '../src' +import { computeConstructorIdFromEntry, computeConstructorIdFromString, TlArgument, TlEntry } from '../src' describe('computeConstructorIdFromString', () => { const test = (tl: string, expected: number) => { @@ -23,24 +18,15 @@ describe('computeConstructorIdFromString', () => { }) it('computes for constructors with simple parameters', () => { - test( - 'auth.exportAuthorization dc_id:int = auth.ExportedAuthorization;', - 0xe5bfffcd, - ) + test('auth.exportAuthorization dc_id:int = auth.ExportedAuthorization;', 0xe5bfffcd) }) it('computes for constructors with vector parameters', () => { - test( - 'account.deleteSecureValue types:Vector = Bool;', - 0xb880bc4b, - ) + test('account.deleteSecureValue types:Vector = Bool;', 0xb880bc4b) }) it('computes for constructors with vector return type', () => { - test( - 'account.getSecureValue types:Vector = Vector;', - 0x73665bc2, - ) + test('account.getSecureValue types:Vector = Vector;', 0x73665bc2) }) it('computes for constructors with optional parameters', () => { @@ -105,36 +91,15 @@ describe('computeConstructorIdFromEntry', () => { }) it('computes for constructors with simple parameters', () => { - test( - make( - 'auth.exportAuthorization', - 'auth.ExportedAuthorization', - 'dc_id:int', - ), - 0xe5bfffcd, - ) + test(make('auth.exportAuthorization', 'auth.ExportedAuthorization', 'dc_id:int'), 0xe5bfffcd) }) it('computes for constructors with vector parameters', () => { - test( - make( - 'account.deleteSecureValue', - 'Bool', - 'types:Vector', - ), - 0xb880bc4b, - ) + test(make('account.deleteSecureValue', 'Bool', 'types:Vector'), 0xb880bc4b) }) it('computes for constructors with vector return type', () => { - test( - make( - 'account.getSecureValue', - 'Vector', - 'types:Vector', - ), - 0x73665bc2, - ) + test(make('account.getSecureValue', 'Vector', 'types:Vector'), 0x73665bc2) }) it('computes for constructors with optional parameters', () => { diff --git a/packages/tl-utils/tests/diff.spec.ts b/packages/tl-utils/tests/diff.spec.ts index d159a1b6..20cefb91 100644 --- a/packages/tl-utils/tests/diff.spec.ts +++ b/packages/tl-utils/tests/diff.spec.ts @@ -1,10 +1,7 @@ import { expect } from 'chai' import { describe, it } from 'mocha' -import { - generateTlEntriesDifference, - generateTlSchemasDifference, -} from '../src/diff' +import { generateTlEntriesDifference, generateTlSchemasDifference } from '../src/diff' import { parseTlToEntries } from '../src/parse' import { parseFullTlSchema } from '../src/schema' import { TlEntryDiff, TlSchemaDiff } from '../src/types' @@ -69,54 +66,44 @@ describe('generateTlEntriesDifference', () => { }) it('shows args diff', () => { - test( - [ - 'test#1 foo:int bar:int egg:flags.0?Egg = Test;', - 'test#1 foo:Foo baz:int egg:flags.1?Egg = Test;', - ], - { - name: 'test', - arguments: { - added: [ - { - name: 'baz', - type: 'int', + test(['test#1 foo:int bar:int egg:flags.0?Egg = Test;', 'test#1 foo:Foo baz:int egg:flags.1?Egg = Test;'], { + name: 'test', + arguments: { + added: [ + { + name: 'baz', + type: 'int', + }, + ], + removed: [ + { + name: 'bar', + type: 'int', + }, + ], + modified: [ + { + name: 'foo', + type: { + old: 'int', + new: 'Foo', }, - ], - removed: [ - { - name: 'bar', - type: 'int', + }, + { + name: 'egg', + type: { + old: 'flags.0?Egg', + new: 'flags.1?Egg', }, - ], - modified: [ - { - name: 'foo', - type: { - old: 'int', - new: 'Foo', - }, - }, - { - name: 'egg', - type: { - old: 'flags.0?Egg', - new: 'flags.1?Egg', - }, - }, - ], - }, + }, + ], }, - ) + }) }) }) describe('generateTlSchemasDifference', () => { - const test = ( - tl1: string[], - tl2: string[], - expected: Partial, - ) => { + const test = (tl1: string[], tl2: string[], expected: Partial) => { const a = parseFullTlSchema(parseTlToEntries(tl1.join('\n'))) const b = parseFullTlSchema(parseTlToEntries(tl2.join('\n'))) const res: Partial = generateTlSchemasDifference(a, b) @@ -196,204 +183,131 @@ describe('generateTlSchemasDifference', () => { }) it('shows removed unions', () => { - test( - ['test foo:int = Test;', 'test1 = Test1;'], - ['test foo:Foo = Test;'], - { - unions: { - removed: [ - { - name: 'Test1', - classes: [ - { - kind: 'class', - name: 'test1', - id: 3739166976, - type: 'Test1', - arguments: [], - }, - ], - }, - ], - added: [], - modified: [], - }, + test(['test foo:int = Test;', 'test1 = Test1;'], ['test foo:Foo = Test;'], { + unions: { + removed: [ + { + name: 'Test1', + classes: [ + { + kind: 'class', + name: 'test1', + id: 3739166976, + type: 'Test1', + arguments: [], + }, + ], + }, + ], + added: [], + modified: [], }, - ) + }) }) it('shows added unions', () => { - test( - ['test foo:int = Test;'], - ['test foo:Foo = Test;', 'test1 = Test1;'], - { - unions: { - added: [ - { - name: 'Test1', - classes: [ - { - kind: 'class', - name: 'test1', - id: 3739166976, - type: 'Test1', - arguments: [], - }, - ], - }, - ], - removed: [], - modified: [], - }, + test(['test foo:int = Test;'], ['test foo:Foo = Test;', 'test1 = Test1;'], { + unions: { + added: [ + { + name: 'Test1', + classes: [ + { + kind: 'class', + name: 'test1', + id: 3739166976, + type: 'Test1', + arguments: [], + }, + ], + }, + ], + removed: [], + modified: [], }, - ) + }) }) it('shows modified unions', () => { - test( - ['test foo:int = Test;', 'test1 = Test;'], - ['test foo:Foo = Test;', 'test2 = Test;'], - { - unions: { - added: [], - removed: [], - modified: [ - { - name: 'Test', - classes: { - added: [ - { - kind: 'class', - name: 'test2', - id: 3847402009, - type: 'Test', - arguments: [], - }, - ], - removed: [ - { - kind: 'class', - name: 'test1', - id: 1809692154, - type: 'Test', - arguments: [], - }, - ], - modified: [], - }, - methods: { - added: [], - removed: [], - modified: [], - }, - }, - ], - }, - }, - ) - - test( - ['test foo:int = Test;', 'test1 = Test;'], - ['test2 foo:Foo = Test;', 'test3 = Test;'], - { - unions: { - added: [], - removed: [], - modified: [ - { - name: 'Test', - classes: { - added: [ - { - kind: 'class', - name: 'test2', - id: 711487159, - type: 'Test', - arguments: [ - { - name: 'foo', - type: 'Foo', - }, - ], - }, - { - kind: 'class', - name: 'test3', - id: 704164487, - type: 'Test', - arguments: [], - }, - ], - removed: [ - { - kind: 'class', - name: 'test', - id: 1331975629, - type: 'Test', - arguments: [ - { - name: 'foo', - type: 'int', - }, - ], - }, - { - kind: 'class', - name: 'test1', - id: 1809692154, - type: 'Test', - arguments: [], - }, - ], - modified: [], - }, - methods: { - added: [], - removed: [], - modified: [], - }, - }, - ], - }, - }, - ) - - test( - ['test = Test;', 'test1 = Test;'], - ['test = Test1;', 'test1 = Test1;'], - { - unions: { - added: [ - { - name: 'Test1', - classes: [ + test(['test foo:int = Test;', 'test1 = Test;'], ['test foo:Foo = Test;', 'test2 = Test;'], { + unions: { + added: [], + removed: [], + modified: [ + { + name: 'Test', + classes: { + added: [ { kind: 'class', - name: 'test', - id: 1997819349, - type: 'Test1', - arguments: [], - }, - { - kind: 'class', - name: 'test1', - id: 3739166976, - type: 'Test1', + name: 'test2', + id: 3847402009, + type: 'Test', arguments: [], }, ], + removed: [ + { + kind: 'class', + name: 'test1', + id: 1809692154, + type: 'Test', + arguments: [], + }, + ], + modified: [], }, - ], - removed: [ - { - name: 'Test', - classes: [ + methods: { + added: [], + removed: [], + modified: [], + }, + }, + ], + }, + }) + + test(['test foo:int = Test;', 'test1 = Test;'], ['test2 foo:Foo = Test;', 'test3 = Test;'], { + unions: { + added: [], + removed: [], + modified: [ + { + name: 'Test', + classes: { + added: [ + { + kind: 'class', + name: 'test2', + id: 711487159, + type: 'Test', + arguments: [ + { + name: 'foo', + type: 'Foo', + }, + ], + }, + { + kind: 'class', + name: 'test3', + id: 704164487, + type: 'Test', + arguments: [], + }, + ], + removed: [ { kind: 'class', name: 'test', - id: 471282454, + id: 1331975629, type: 'Test', - arguments: [], + arguments: [ + { + name: 'foo', + type: 'int', + }, + ], }, { kind: 'class', @@ -403,11 +317,64 @@ describe('generateTlSchemasDifference', () => { arguments: [], }, ], + modified: [], }, - ], - modified: [], - }, + methods: { + added: [], + removed: [], + modified: [], + }, + }, + ], }, - ) + }) + + test(['test = Test;', 'test1 = Test;'], ['test = Test1;', 'test1 = Test1;'], { + unions: { + added: [ + { + name: 'Test1', + classes: [ + { + kind: 'class', + name: 'test', + id: 1997819349, + type: 'Test1', + arguments: [], + }, + { + kind: 'class', + name: 'test1', + id: 3739166976, + type: 'Test1', + arguments: [], + }, + ], + }, + ], + removed: [ + { + name: 'Test', + classes: [ + { + kind: 'class', + name: 'test', + id: 471282454, + type: 'Test', + arguments: [], + }, + { + kind: 'class', + name: 'test1', + id: 1809692154, + type: 'Test', + arguments: [], + }, + ], + }, + ], + modified: [], + }, + }) }) }) diff --git a/packages/tl-utils/tests/merge.spec.ts b/packages/tl-utils/tests/merge.spec.ts index 620e0521..408200fe 100644 --- a/packages/tl-utils/tests/merge.spec.ts +++ b/packages/tl-utils/tests/merge.spec.ts @@ -22,10 +22,7 @@ describe('mergeTlEntries', () => { } it('fails on conflicting kinds', () => { - test( - 'test = Test;\n---functions---\ntest = Test;', - 'basic info mismatch', - ) + test('test = Test;\n---functions---\ntest = Test;', 'basic info mismatch') }) it('fails on conflicting names', () => { @@ -75,15 +72,9 @@ describe('mergeTlEntries', () => { }) describe('mergeTlSchemas', () => { - const test = async ( - schemas: string[][], - onConflict: number, - ...expected: string[] - ) => { + const test = async (schemas: string[][], onConflict: number, ...expected: string[]) => { const res = await mergeTlSchemas( - schemas.map((tl) => - parseFullTlSchema(parseTlToEntries(tl.join('\n'))), - ), + schemas.map((tl) => parseFullTlSchema(parseTlToEntries(tl.join('\n')))), (opts) => opts[onConflict], ) @@ -97,11 +88,7 @@ describe('mergeTlSchemas', () => { it('merges different constructors', async () => { await test( - [ - ['testClass = Test;'], - ['testClass2 = Test;'], - ['---functions---', 'testMethod = Test;'], - ], + [['testClass = Test;'], ['testClass2 = Test;'], ['---functions---', 'testMethod = Test;']], 0, 'testClass#5d60a438 = Test;', 'testClass2#39c5c841 = Test;', @@ -124,28 +111,16 @@ describe('mergeTlSchemas', () => { it('resolves conflict using user-provided option', async () => { await test( - [ - ['test foo:int = Test;'], - ['test bar:int = Test;'], - ['test baz:int = Test;'], - ], + [['test foo:int = Test;'], ['test bar:int = Test;'], ['test baz:int = Test;']], 0, 'test#4f6455cd foo:int = Test;', ) await test( - [ - ['test foo:int = Test;'], - ['test bar:int = Test;'], - ['test baz:int = Test;'], - ], + [['test foo:int = Test;'], ['test bar:int = Test;'], ['test baz:int = Test;']], 1, 'test#3e993a74 bar:int = Test;', ) - await test( - [['test foo:int = Test;'], [], ['test bar:int = Test;']], - 1, - '', - ) + await test([['test foo:int = Test;'], [], ['test bar:int = Test;']], 1, '') }) it('merges comments', async () => { @@ -153,10 +128,7 @@ describe('mergeTlSchemas', () => { [ ['test foo:flags.0?true = Test;'], ['// test ctor', 'test bar:flags.0?true = Test;'], - [ - '// will be ignored', - 'test foo:flags.0?true bar:flags.0?true = Test;', - ], + ['// will be ignored', 'test foo:flags.0?true bar:flags.0?true = Test;'], ], 0, '// @description test ctor', @@ -168,14 +140,8 @@ describe('mergeTlSchemas', () => { await test( [ ['test foo:flags.0?true = Test;'], - [ - '// @description test @bar bar comment', - 'test bar:flags.0?true = Test;', - ], - [ - '// @description test @foo foo comment', - 'test foo:flags.0?true bar:flags.0?true = Test;', - ], + ['// @description test @bar bar comment', 'test bar:flags.0?true = Test;'], + ['// @description test @foo foo comment', 'test foo:flags.0?true bar:flags.0?true = Test;'], ], 0, '// @description test', diff --git a/packages/tl-utils/tests/parse.spec.ts b/packages/tl-utils/tests/parse.spec.ts index 28e193c5..0433c924 100644 --- a/packages/tl-utils/tests/parse.spec.ts +++ b/packages/tl-utils/tests/parse.spec.ts @@ -4,11 +4,7 @@ import { describe, it } from 'mocha' import { parseTlToEntries, TlEntry } from '../src' describe('tl parser', () => { - const test = ( - tl: string, - expected: TlEntry[], - params?: Parameters[1], - ) => { + const test = (tl: string, expected: TlEntry[], params?: Parameters[1]) => { expect(parseTlToEntries(tl, params)).eql(expected) } @@ -94,34 +90,31 @@ boolTrue#997275b5 = Bool; it('parses bare vectors', () => { // note: not from schema, schema uses bare `future_salt` instead - test( - 'future_salts#ae500895 req_msg_id:long now:int salts:vector = FutureSalts;', - [ - { - kind: 'class', - name: 'future_salts', - id: 0xae500895, - type: 'FutureSalts', - arguments: [ - { - name: 'req_msg_id', - type: 'long', + test('future_salts#ae500895 req_msg_id:long now:int salts:vector = FutureSalts;', [ + { + kind: 'class', + name: 'future_salts', + id: 0xae500895, + type: 'FutureSalts', + arguments: [ + { + name: 'req_msg_id', + type: 'long', + }, + { + name: 'now', + type: 'int', + }, + { + name: 'salts', + type: 'FutureSalt', + typeModifiers: { + isBareVector: true, }, - { - name: 'now', - type: 'int', - }, - { - name: 'salts', - type: 'FutureSalt', - typeModifiers: { - isBareVector: true, - }, - }, - ], - }, - ], - ) + }, + ], + }, + ]) }) it('parses bare unions', () => { @@ -199,80 +192,71 @@ boolTrue#997275b5 = Bool; }) it('parses methods with arguments', () => { - test( - '---functions---\nauth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;', - [ - { - kind: 'method', - name: 'auth.exportAuthorization', - id: 0xe5bfffcd, - type: 'auth.ExportedAuthorization', - arguments: [ - { - name: 'dc_id', - type: 'int', - }, - ], - }, - ], - ) + test('---functions---\nauth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;', [ + { + kind: 'method', + name: 'auth.exportAuthorization', + id: 0xe5bfffcd, + type: 'auth.ExportedAuthorization', + arguments: [ + { + name: 'dc_id', + type: 'int', + }, + ], + }, + ]) }) it('parses multiple classes', () => { - test( - 'jsonNull#3f6d7b68 = JSONValue;\njsonBool#c7345e6a value:Bool = JSONValue;', - [ - { - kind: 'class', - name: 'jsonNull', - id: 0x3f6d7b68, - type: 'JSONValue', - arguments: [], - }, - { - kind: 'class', - name: 'jsonBool', - id: 0xc7345e6a, - type: 'JSONValue', - arguments: [ - { - name: 'value', - type: 'Bool', - }, - ], - }, - ], - ) + test('jsonNull#3f6d7b68 = JSONValue;\njsonBool#c7345e6a value:Bool = JSONValue;', [ + { + kind: 'class', + name: 'jsonNull', + id: 0x3f6d7b68, + type: 'JSONValue', + arguments: [], + }, + { + kind: 'class', + name: 'jsonBool', + id: 0xc7345e6a, + type: 'JSONValue', + arguments: [ + { + name: 'value', + type: 'Bool', + }, + ], + }, + ]) }) it('parses generics', () => { - test( - '---functions---\ninvokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;', - [ - { - kind: 'method', - name: 'invokeWithLayer', - id: 0xda9b0d0d, - type: 'X', - generics: [ - { - name: 'X', - type: 'Type', - }, - ], - arguments: [ - { - name: 'layer', - type: 'int', - }, - { - name: 'query', - type: '!X', - }, - ], - }, - ], - ) + test('---functions---\ninvokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;', [ + { + kind: 'method', + name: 'invokeWithLayer', + id: 0xda9b0d0d, + type: 'X', + generics: [ + { + name: 'X', + type: 'Type', + }, + ], + arguments: [ + { + name: 'layer', + type: 'int', + }, + { + name: 'query', + type: '!X', + }, + ], + }, + ]) }) it('parses predicates', () => { @@ -411,20 +395,13 @@ users.getUsers id:Vector = Vector; it('calls callback on orphan comment', () => { const orphaned: string[] = [] parseTlToEntries( - '// some comment idk\n\n' + - '//another comment\n' + - '//but multiline\n\n' + - '//yet another at the end', + '// some comment idk\n\n' + '//another comment\n' + '//but multiline\n\n' + '//yet another at the end', { onOrphanComment: (s) => orphaned.push(s), }, ) - expect(orphaned).eql([ - 'some comment idk', - 'another comment but multiline', - 'yet another at the end', - ]) + expect(orphaned).eql(['some comment idk', 'another comment but multiline', 'yet another at the end']) }) it('applies prefix to constructors', () => { diff --git a/packages/tl-utils/tests/schema.spec.ts b/packages/tl-utils/tests/schema.spec.ts index a59e5c5c..69b69f38 100644 --- a/packages/tl-utils/tests/schema.spec.ts +++ b/packages/tl-utils/tests/schema.spec.ts @@ -5,11 +5,7 @@ import { writeTlEntriesToString } from '../src/schema' import { TlEntry } from '../src/types' describe('writeTlEntriesToString', () => { - const test = ( - entries: TlEntry[], - params: Parameters[1], - ...expected: string[] - ) => { + const test = (entries: TlEntry[], params: Parameters[1], ...expected: string[]) => { expect( writeTlEntriesToString(entries, { omitPrimitives: true, @@ -36,11 +32,7 @@ describe('writeTlEntriesToString', () => { ], } - test( - [obj], - { computeIds: false }, - 'error code:int text:string = Error;', - ) + test([obj], { computeIds: false }, 'error code:int text:string = Error;') test([obj], {}, 'error#c4b9f9bb code:int text:string = Error;') }) @@ -65,21 +57,10 @@ describe('writeTlEntriesToString', () => { comment: 'An error', } - test( - [obj], - {}, - '// An error', - 'error#c4b9f9bb code:int text:string = Error;', - ) + test([obj], {}, '// An error', 'error#c4b9f9bb code:int text:string = Error;') obj.comment += '\nVery error' - test( - [obj], - {}, - '// An error', - '//- Very error', - 'error#c4b9f9bb code:int text:string = Error;', - ) + test([obj], {}, '// An error', '//- Very error', 'error#c4b9f9bb code:int text:string = Error;') }) it('writes tdlib-style comments', () => { diff --git a/packages/tl-utils/tests/stringify.spec.ts b/packages/tl-utils/tests/stringify.spec.ts index a0e82cc2..aae001f4 100644 --- a/packages/tl-utils/tests/stringify.spec.ts +++ b/packages/tl-utils/tests/stringify.spec.ts @@ -37,10 +37,7 @@ describe('writeTlEntryToString', () => { it('writes constructors without parameters', () => { test(make('auth.logOut', 'Bool'), 'auth.logOut = Bool;') - test( - make('auth.resetAuthorizations', 'Bool'), - 'auth.resetAuthorizations = Bool;', - ) + test(make('auth.resetAuthorizations', 'Bool'), 'auth.resetAuthorizations = Bool;') }) it('writes constructor id if available', () => { @@ -51,33 +48,21 @@ describe('writeTlEntryToString', () => { it('writes constructors with simple parameters', () => { test( - make( - 'auth.exportAuthorization', - 'auth.ExportedAuthorization', - 'dc_id:int', - ), + make('auth.exportAuthorization', 'auth.ExportedAuthorization', 'dc_id:int'), 'auth.exportAuthorization dc_id:int = auth.ExportedAuthorization;', ) }) it('computes for constructors with vector parameters', () => { test( - make( - 'account.deleteSecureValue', - 'Bool', - 'types:Vector', - ), + make('account.deleteSecureValue', 'Bool', 'types:Vector'), 'account.deleteSecureValue types:Vector = Bool;', ) }) it('computes for constructors with vector return type', () => { test( - make( - 'account.getSecureValue', - 'Vector', - 'types:Vector', - ), + make('account.getSecureValue', 'Vector', 'types:Vector'), 'account.getSecureValue types:Vector = Vector;', ) }) diff --git a/packages/tl/scripts/constants.ts b/packages/tl/scripts/constants.ts index 6e808794..a0a82b64 100644 --- a/packages/tl/scripts/constants.ts +++ b/packages/tl/scripts/constants.ts @@ -1,10 +1,7 @@ import { join } from 'path' export const DOC_CACHE_FILE = join(__dirname, '.documentation.cache.json') -export const DESCRIPTIONS_YAML_FILE = join( - __dirname, - '../data/descriptions.yaml', -) +export const DESCRIPTIONS_YAML_FILE = join(__dirname, '../data/descriptions.yaml') export const API_SCHEMA_JSON_FILE = join(__dirname, '../api-schema.json') export const API_SCHEMA_DIFF_JSON_FILE = join(__dirname, '../diff.json') export const MTP_SCHEMA_JSON_FILE = join(__dirname, '../mtp-schema.json') @@ -18,8 +15,7 @@ export const TDESKTOP_SCHEMA = 'https://raw.githubusercontent.com/telegramdesktop/tdesktop/dev/Telegram/SourceFiles/mtproto/scheme/api.tl' export const TDESKTOP_LAYER = 'https://raw.githubusercontent.com/telegramdesktop/tdesktop/dev/Telegram/SourceFiles/mtproto/scheme/layer.tl' -export const TDLIB_SCHEMA = - 'https://raw.githubusercontent.com/tdlib/td/master/td/generate/scheme/telegram_api.tl' +export const TDLIB_SCHEMA = 'https://raw.githubusercontent.com/tdlib/td/master/td/generate/scheme/telegram_api.tl' export const ESM_PRELUDE = `// This file is auto-generated. Do not edit. "use strict"; diff --git a/packages/tl/scripts/documentation.ts b/packages/tl/scripts/documentation.ts index 525364e0..c54d105d 100644 --- a/packages/tl/scripts/documentation.ts +++ b/packages/tl/scripts/documentation.ts @@ -38,10 +38,7 @@ export interface CachedDocumentation { unions: Record } -function normalizeLinks( - url: string, - el: cheerio.Cheerio, -): void { +function normalizeLinks(url: string, el: cheerio.Cheerio): void { el.find('a').each((i, _it) => { const it = cheerio.default(_it) let href = it.attr('href') @@ -54,9 +51,7 @@ function normalizeLinks( let m - if ( - (m = href.match(/\/(constructor|method|union)\/([^#?]+)(?:\?|#|$)/)) - ) { + if ((m = href.match(/\/(constructor|method|union)\/([^#?]+)(?:\?|#|$)/))) { const [, type, name] = m const [ns, n] = splitNameToNamespace(name) @@ -95,9 +90,7 @@ function extractDescription($: cheerio.CheerioAPI) { // from https://github.com/sindresorhus/cli-spinners/blob/main/spinners.json const PROGRESS_CHARS = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'] -async function chooseDomainForDocs( - headers: Record, -): Promise<[number, string]> { +async function chooseDomainForDocs(headers: Record): Promise<[number, string]> { let maxLayer = 0 let maxDomain = '' @@ -140,9 +133,7 @@ export async function fetchDocumentation( console.log('Using domain %s (has layer %s)', domain, actualLayer) const ret: CachedDocumentation = { - updated: `${new Date().toLocaleString( - 'ru-RU', - )} (layer ${actualLayer}) - from ${domain}`, + updated: `${new Date().toLocaleString('ru-RU')} (layer ${actualLayer}) - from ${domain}`, classes: {}, methods: {}, unions: {}, @@ -164,9 +155,7 @@ export async function fetchDocumentation( for (const entry of schema.entries) { log(`📥 ${entry.kind} ${entry.name}`) - const url = `${domain}/${ - entry.kind === 'class' ? 'constructor' : 'method' - }/${entry.name}` + const url = `${domain}/${entry.kind === 'class' ? 'constructor' : 'method'}/${entry.name}` const html = await fetchRetry(url, { headers, @@ -223,9 +212,7 @@ export async function fetchDocumentation( const botsCanUse = Boolean($('#bots-can-use-this-method').length) const onlyBotsCanUse = - botsCanUse && - (Boolean(description.match(/[,;]( for)? bots only$/)) || - userBotRequired) + botsCanUse && (Boolean(description.match(/[,;]( for)? bots only$/)) || userBotRequired) if (onlyBotsCanUse) { retClass.available = 'bot' @@ -236,8 +223,7 @@ export async function fetchDocumentation( } } - ret[entry.kind === 'class' ? 'classes' : 'methods'][entry.name] = - retClass + ret[entry.kind === 'class' ? 'classes' : 'methods'][entry.name] = retClass } for (const name in schema.unions) { @@ -261,9 +247,7 @@ export async function fetchDocumentation( log('✨ Patching descriptions') - const descriptionsYaml = jsYaml.load( - await readFile(DESCRIPTIONS_YAML_FILE, 'utf8'), - ) + const descriptionsYaml = jsYaml.load(await readFile(DESCRIPTIONS_YAML_FILE, 'utf8')) applyDescriptionsYamlFile(ret, descriptionsYaml) log('🔄 Writing to file') @@ -275,10 +259,7 @@ export async function fetchDocumentation( return ret } -export function applyDocumentation( - schema: TlFullSchema, - docs: CachedDocumentation, -) { +export function applyDocumentation(schema: TlFullSchema, docs: CachedDocumentation) { for (let i = 0; i < 2; i++) { const kind = i === 0 ? 'classes' : 'methods' @@ -337,8 +318,7 @@ async function main() { input: process.stdin, output: process.stdout, }) - const input = (q: string): Promise => - new Promise((res) => rl.question(q, res)) + const input = (q: string): Promise => new Promise((res) => rl.question(q, res)) while (true) { console.log('Choose action:') @@ -358,9 +338,7 @@ async function main() { if (act === 1) { const [schema, layer] = unpackTlSchema( - JSON.parse( - await readFile(API_SCHEMA_JSON_FILE, 'utf8'), - ) as TlPackedSchema, + JSON.parse(await readFile(API_SCHEMA_JSON_FILE, 'utf8')) as TlPackedSchema, ) cached = await fetchDocumentation(schema, layer) } @@ -371,9 +349,7 @@ async function main() { continue } - const descriptionsYaml = jsYaml.load( - await readFile(DESCRIPTIONS_YAML_FILE, 'utf8'), - ) + const descriptionsYaml = jsYaml.load(await readFile(DESCRIPTIONS_YAML_FILE, 'utf8')) applyDescriptionsYamlFile(cached, descriptionsYaml) await writeFile(DOC_CACHE_FILE, JSON.stringify(cached)) @@ -386,16 +362,11 @@ async function main() { } const [schema, layer] = unpackTlSchema( - JSON.parse( - await readFile(API_SCHEMA_JSON_FILE, 'utf8'), - ) as TlPackedSchema, + JSON.parse(await readFile(API_SCHEMA_JSON_FILE, 'utf8')) as TlPackedSchema, ) applyDocumentation(schema, cached) - await writeFile( - API_SCHEMA_JSON_FILE, - JSON.stringify(packTlSchema(schema, layer)), - ) + await writeFile(API_SCHEMA_JSON_FILE, JSON.stringify(packTlSchema(schema, layer))) } } } diff --git a/packages/tl/scripts/fetch-api.ts b/packages/tl/scripts/fetch-api.ts index 8b79823b..20fc1a00 100644 --- a/packages/tl/scripts/fetch-api.ts +++ b/packages/tl/scripts/fetch-api.ts @@ -31,11 +31,7 @@ import { TDESKTOP_SCHEMA, TDLIB_SCHEMA, } from './constants' -import { - applyDocumentation, - fetchDocumentation, - getCachedDocumentation, -} from './documentation' +import { applyDocumentation, fetchDocumentation, getCachedDocumentation } from './documentation' import { packTlSchema, TlPackedSchema, unpackTlSchema } from './schema' import { fetchRetry } from './utils' @@ -60,9 +56,9 @@ interface Schema { async function fetchTdlibSchema(): Promise { const schema = await fetchRetry(TDLIB_SCHEMA) - const versionHtml = await fetch( - 'https://raw.githubusercontent.com/tdlib/td/master/td/telegram/Version.h', - ).then((i) => i.text()) + const versionHtml = await fetch('https://raw.githubusercontent.com/tdlib/td/master/td/telegram/Version.h').then( + (i) => i.text(), + ) const layer = versionHtml.match(/^constexpr int32 MTPROTO_LAYER = (\d+)/m) if (!layer) throw new Error('Layer number not available') @@ -87,17 +83,11 @@ async function fetchTdesktopSchema(): Promise { } } -async function fetchCoreSchema( - domain = CORE_DOMAIN, - name = 'Core', -): Promise { +async function fetchCoreSchema(domain = CORE_DOMAIN, name = 'Core'): Promise { const html = await fetchRetry(`${domain}/schema`) const $ = cheerio.load(html) // cheerio doesn't always unescape them - const schema = $('.page_scheme code') - .text() - .replace(/</g, '<') - .replace(/>/g, '>') + const schema = $('.page_scheme code').text().replace(/</g, '<').replace(/>/g, '>') const layer = $('.dev_layer_select .dropdown-toggle') .text() @@ -133,13 +123,8 @@ async function updateReadme(currentLayer: number) { ) } -async function updatePackageVersion( - rl: readline.Interface, - currentLayer: number, -) { - const packageJson = JSON.parse( - await readFile(PACKAGE_JSON_FILE, 'utf8'), - ) as { version: string } +async function updatePackageVersion(rl: readline.Interface, currentLayer: number) { + const packageJson = JSON.parse(await readFile(PACKAGE_JSON_FILE, 'utf8')) as { version: string } const version = packageJson.version let [major, minor] = version.split('.').map((i) => parseInt(i)) @@ -168,9 +153,10 @@ async function updatePackageVersion( async function overrideInt53(schema: TlFullSchema): Promise { console.log('Applying int53 overrides...') - const config = JSON.parse( - await readFile(join(__dirname, '../data/int53-overrides.json'), 'utf8'), - ) as Record> + const config = JSON.parse(await readFile(join(__dirname, '../data/int53-overrides.json'), 'utf8')) as Record< + string, + Record + > schema.entries.forEach((entry) => { const overrides: string[] | undefined = config[entry.kind][entry.name] @@ -180,9 +166,7 @@ async function overrideInt53(schema: TlFullSchema): Promise { const arg = entry.arguments.find((it) => it.name === argName) if (!arg) { - console.log( - `[warn] Cannot override ${entry.name}#${argName}: argument does not exist`, - ) + console.log(`[warn] Cannot override ${entry.name}#${argName}: argument does not exist`) return } @@ -192,9 +176,7 @@ async function overrideInt53(schema: TlFullSchema): Promise { } else if (arg.type.toLowerCase() === 'vector') { arg.type = 'vector' } else { - console.log( - `[warn] Cannot override ${entry.name}#${argName}: argument is not long (${arg.type})`, - ) + console.log(`[warn] Cannot override ${entry.name}#${argName}: argument is not long (${arg.type})`) } }) }) @@ -212,20 +194,13 @@ async function main() { { name: 'Custom', layer: 0, // handled manually - content: tlToFullSchema( - await readFile(join(__dirname, '../data/custom.tl'), 'utf8'), - ), + content: tlToFullSchema(await readFile(join(__dirname, '../data/custom.tl'), 'utf8')), }, ] console.log('Available schemas:') schemas.forEach((schema) => - console.log( - ' - %s (layer %d): %d entries', - schema.name, - schema.layer, - schema.content.entries.length, - ), + console.log(' - %s (layer %d): %d entries', schema.name, schema.layer, schema.content.entries.length), ) const resultLayer = Math.max(...schemas.map((it) => it.layer)) @@ -253,9 +228,7 @@ async function main() { chooseOptions = options } else { // first of all, prefer entries from the latest layer - const fromLastSchema = options.filter( - (opt) => opt.schema.layer === resultLayer, - ) + const fromLastSchema = options.filter((opt) => opt.schema.layer === resultLayer) // if there is only one schema on the latest layer, we can simply return it if (fromLastSchema.length === 1) return fromLastSchema[0].entry @@ -263,9 +236,7 @@ async function main() { // there are multiple choices on the latest layer // if they are all the same, it's just conflict between layers, // and we can merge the ones from the latest layer - const mergedEntry = mergeTlEntries( - fromLastSchema.map((opt) => opt.entry).filter(isPresent), - ) + const mergedEntry = mergeTlEntries(fromLastSchema.map((opt) => opt.entry).filter(isPresent)) if (typeof mergedEntry === 'string') { // merge failed, so there is in fact some conflict chooseOptions = fromLastSchema @@ -274,24 +245,14 @@ async function main() { const nonEmptyOptions = chooseOptions.filter(hasPresentKey('entry')) - console.log( - 'Conflict detected at %s %s:', - nonEmptyOptions[0].entry.kind, - nonEmptyOptions[0].entry.name, - ) + console.log('Conflict detected at %s %s:', nonEmptyOptions[0].entry.kind, nonEmptyOptions[0].entry.name) console.log('0. Remove') nonEmptyOptions.forEach((opt, idx) => { - console.log( - `${idx + 1}. ${opt.schema.name}: ${writeTlEntryToString( - opt.entry, - )}`, - ) + console.log(`${idx + 1}. ${opt.schema.name}: ${writeTlEntryToString(opt.entry)}`) }) while (true) { - const res = parseInt( - await input(rl, `[0-${nonEmptyOptions.length}] > `), - ) + const res = parseInt(await input(rl, `[0-${nonEmptyOptions.length}] > `)) if (isNaN(res) || res < 0 || res > nonEmptyOptions.length) { continue @@ -304,10 +265,7 @@ async function main() { }, ) - console.log( - 'Done! Final schema contains %d entries', - resultSchema.entries.length, - ) + console.log('Done! Final schema contains %d entries', resultSchema.entries.length) let docs = await getCachedDocumentation() @@ -330,11 +288,7 @@ async function main() { await overrideInt53(resultSchema) console.log('Writing diff to file...') - const oldSchema = unpackTlSchema( - JSON.parse( - await readFile(API_SCHEMA_JSON_FILE, 'utf8'), - ) as TlPackedSchema, - ) + const oldSchema = unpackTlSchema(JSON.parse(await readFile(API_SCHEMA_JSON_FILE, 'utf8')) as TlPackedSchema) await writeFile( API_SCHEMA_DIFF_JSON_FILE, JSON.stringify( @@ -348,10 +302,7 @@ async function main() { ) console.log('Writing result to file...') - await writeFile( - API_SCHEMA_JSON_FILE, - JSON.stringify(packTlSchema(resultSchema, resultLayer)), - ) + await writeFile(API_SCHEMA_JSON_FILE, JSON.stringify(packTlSchema(resultSchema, resultLayer))) console.log('Updating README.md...') await updateReadme(resultLayer) diff --git a/packages/tl/scripts/fetch-errors.ts b/packages/tl/scripts/fetch-errors.ts index 305d3d2e..bfe2c5bf 100644 --- a/packages/tl/scripts/fetch-errors.ts +++ b/packages/tl/scripts/fetch-errors.ts @@ -28,14 +28,10 @@ interface TelegramErrorsSpec { async function fetchFromTelegram(errors: TlErrors) { const page = await fetch(ERRORS_PAGE_TG).then((it) => it.text()) - const jsonUrl = page.match( - /can be found here »<\/a>/i, - )?.[1] + const jsonUrl = page.match(/can be found here »<\/a>/i)?.[1] if (!jsonUrl) throw new Error('Cannot find JSON URL') - const json = (await fetch(new URL(jsonUrl, ERRORS_PAGE_TG)).then((it) => - it.json(), - )) as TelegramErrorsSpec + const json = (await fetch(new URL(jsonUrl, ERRORS_PAGE_TG)).then((it) => it.json())) as TelegramErrorsSpec // since nobody fucking guarantees that .descriptions // will have description for each described here (or vice versa), @@ -103,8 +99,7 @@ async function fetchFromTelegram(errors: TlErrors) { matchingErrors.push(inner) if (!errors.errors[inner].description) { - errors.errors[inner].description = - errors.errors[name].description + errors.errors[inner].description = errors.errors[name].description } } @@ -176,17 +171,14 @@ async function fetchFromTelethon(errors: TlErrors) { // names for better code insights // we also prefer description from telegram, if it's available and doesn't use placeholders if (description) { - const desc = description.replace( - /{([a-z0-9_]+)}/gi, - (_, name: string) => { - if (!obj._paramNames) { - obj._paramNames = [] - } - obj._paramNames.push(name) + const desc = description.replace(/{([a-z0-9_]+)}/gi, (_, name: string) => { + if (!obj._paramNames) { + obj._paramNames = [] + } + obj._paramNames.push(name) - return '%d' - }, - ) + return '%d' + }) if (!obj.description || obj._paramNames?.length) { obj.description = desc diff --git a/packages/tl/scripts/fetch-mtp.ts b/packages/tl/scripts/fetch-mtp.ts index 5633eb27..c12463cc 100644 --- a/packages/tl/scripts/fetch-mtp.ts +++ b/packages/tl/scripts/fetch-mtp.ts @@ -13,10 +13,7 @@ async function fetchMtprotoSchema(): Promise { const $ = cheerio.load(html) // cheerio doesn't always unescape them - return $('#dev_page_content pre code') - .text() - .replace(/</g, '<') - .replace(/>/g, '>') + return $('#dev_page_content pre code').text().replace(/</g, '<').replace(/>/g, '>') } async function main() { @@ -28,14 +25,7 @@ async function main() { // remove manually parsed types entries = entries.filter( - (it) => - ![ - 'mt_msg_container', - 'mt_message', - 'mt_msg_copy', - 'mt_gzip_packed', - 'mt_rpc_result', - ].includes(it.name), + (it) => !['mt_msg_container', 'mt_message', 'mt_msg_copy', 'mt_gzip_packed', 'mt_rpc_result'].includes(it.name), ) // mtproto is handled internally, for simplicity we make them all classes diff --git a/packages/tl/scripts/gen-code.ts b/packages/tl/scripts/gen-code.ts index 760880c3..20fb2794 100644 --- a/packages/tl/scripts/gen-code.ts +++ b/packages/tl/scripts/gen-code.ts @@ -11,12 +11,7 @@ import { TlFullSchema, } from '@mtcute/tl-utils' -import { - API_SCHEMA_JSON_FILE, - ERRORS_JSON_FILE, - ESM_PRELUDE, - MTP_SCHEMA_JSON_FILE, -} from './constants' +import { API_SCHEMA_JSON_FILE, ERRORS_JSON_FILE, ESM_PRELUDE, MTP_SCHEMA_JSON_FILE } from './constants' import { TlPackedSchema, unpackTlSchema } from './schema' const OUT_TYPINGS_FILE = join(__dirname, '../index.d.ts') @@ -24,36 +19,16 @@ const OUT_TYPINGS_JS_FILE = join(__dirname, '../index.js') const OUT_READERS_FILE = join(__dirname, '../binary/reader.js') const OUT_WRITERS_FILE = join(__dirname, '../binary/writer.js') -async function generateTypings( - apiSchema: TlFullSchema, - apiLayer: number, - mtpSchema: TlFullSchema, - errors: TlErrors, -) { +async function generateTypings(apiSchema: TlFullSchema, apiLayer: number, mtpSchema: TlFullSchema, errors: TlErrors) { console.log('Generating typings...') - const [apiTs, apiJs] = generateTypescriptDefinitionsForTlSchema( - apiSchema, - apiLayer, - undefined, - errors, - ) - const [mtpTs, mtpJs] = generateTypescriptDefinitionsForTlSchema( - mtpSchema, - 0, - 'mtp', - ) + const [apiTs, apiJs] = generateTypescriptDefinitionsForTlSchema(apiSchema, apiLayer, undefined, errors) + const [mtpTs, mtpJs] = generateTypescriptDefinitionsForTlSchema(mtpSchema, 0, 'mtp') - await writeFile( - OUT_TYPINGS_FILE, - apiTs + '\n\n' + mtpTs.replace("import _Long from 'long';", ''), - ) + await writeFile(OUT_TYPINGS_FILE, apiTs + '\n\n' + mtpTs.replace("import _Long from 'long';", '')) await writeFile(OUT_TYPINGS_JS_FILE, ESM_PRELUDE + apiJs + '\n\n' + mtpJs) } -async function generateReaders( - apiSchema: TlFullSchema, - mtpSchema: TlFullSchema, -) { +async function generateReaders(apiSchema: TlFullSchema, mtpSchema: TlFullSchema) { console.log('Generating readers...') let code = generateReaderCodeForTlEntries(apiSchema.entries, { @@ -71,19 +46,13 @@ async function generateReaders( await writeFile(OUT_READERS_FILE, ESM_PRELUDE + code) } -async function generateWriters( - apiSchema: TlFullSchema, - mtpSchema: TlFullSchema, -) { +async function generateWriters(apiSchema: TlFullSchema, mtpSchema: TlFullSchema) { console.log('Generating writers...') - let code = generateWriterCodeForTlEntries( - [...apiSchema.entries, ...mtpSchema.entries], - { - variableName: 'm', - includeStaticSizes: true, - }, - ) + let code = generateWriterCodeForTlEntries([...apiSchema.entries, ...mtpSchema.entries], { + variableName: 'm', + includeStaticSizes: true, + }) code += '\nexports.default = m;' @@ -91,18 +60,12 @@ async function generateWriters( } async function main() { - const errors = JSON.parse( - await readFile(ERRORS_JSON_FILE, 'utf8'), - ) as TlErrors + const errors = JSON.parse(await readFile(ERRORS_JSON_FILE, 'utf8')) as TlErrors const [apiSchema, apiLayer] = unpackTlSchema( - JSON.parse( - await readFile(API_SCHEMA_JSON_FILE, 'utf8'), - ) as TlPackedSchema, - ) - const mtpSchema = parseFullTlSchema( - JSON.parse(await readFile(MTP_SCHEMA_JSON_FILE, 'utf8')) as TlEntry[], + JSON.parse(await readFile(API_SCHEMA_JSON_FILE, 'utf8')) as TlPackedSchema, ) + const mtpSchema = parseFullTlSchema(JSON.parse(await readFile(MTP_SCHEMA_JSON_FILE, 'utf8')) as TlEntry[]) await generateTypings(apiSchema, apiLayer, mtpSchema, errors) await generateReaders(apiSchema, mtpSchema) diff --git a/packages/tl/scripts/gen-rsa-keys.ts b/packages/tl/scripts/gen-rsa-keys.ts index 85294401..76bb4906 100644 --- a/packages/tl/scripts/gen-rsa-keys.ts +++ b/packages/tl/scripts/gen-rsa-keys.ts @@ -53,13 +53,7 @@ async function main() { obj[parsed.fingerprint] = parsed } - await writeFile( - OUT_JS_FILE, - ESM_PRELUDE + - "exports.default=JSON.parse('" + - JSON.stringify(obj) + - "');", - ) + await writeFile(OUT_JS_FILE, ESM_PRELUDE + "exports.default=JSON.parse('" + JSON.stringify(obj) + "');") } main().catch(console.error) diff --git a/packages/tl/scripts/process-descriptions-yaml.ts b/packages/tl/scripts/process-descriptions-yaml.ts index 0e4cfbf1..6606ae03 100644 --- a/packages/tl/scripts/process-descriptions-yaml.ts +++ b/packages/tl/scripts/process-descriptions-yaml.ts @@ -48,23 +48,13 @@ function unwrapMaybe(what: MaybeOverwrite, has: boolean): string | undefined { return undefined } -export function applyDescriptionsYamlFile( - input: CachedDocumentation, - yaml: unknown, -) { - const { - objects: byObjects, - arguments: byArguments, - regex: byRegex, - } = yaml as DescriptionsYaml +export function applyDescriptionsYamlFile(input: CachedDocumentation, yaml: unknown) { + const { objects: byObjects, arguments: byArguments, regex: byRegex } = yaml as DescriptionsYaml // first create an index of all classes and methods const objIndex: Record = {} - function indexObject( - obj: Record, - prefix: string, - ) { + function indexObject(obj: Record, prefix: string) { for (const name in obj) { objIndex[prefix + name] = obj[name]! } @@ -87,10 +77,7 @@ export function applyDescriptionsYamlFile( if (rules.arguments) { for (const arg in rules.arguments) { - const repl = unwrapMaybe( - rules.arguments[arg]!, - obj.arguments !== undefined && arg in obj.arguments, - ) + const repl = unwrapMaybe(rules.arguments[arg]!, obj.arguments !== undefined && arg in obj.arguments) if (repl) { if (!obj.arguments) obj.arguments = {} @@ -107,10 +94,7 @@ export function applyDescriptionsYamlFile( for (const arg in byArguments) { if (obj.arguments && !(arg in obj.arguments)) continue - const repl = unwrapMaybe( - byArguments[arg]!, - Boolean(obj.arguments && arg in obj.arguments), - ) + const repl = unwrapMaybe(byArguments[arg]!, Boolean(obj.arguments && arg in obj.arguments)) if (repl) { if (!obj.arguments) obj.arguments = {} diff --git a/packages/tl/scripts/schema.ts b/packages/tl/scripts/schema.ts index 9a20deec..579505f1 100644 --- a/packages/tl/scripts/schema.ts +++ b/packages/tl/scripts/schema.ts @@ -20,10 +20,7 @@ export interface TlPackedSchema { u: Record } -export function packTlSchema( - schema: TlFullSchema, - layer: number, -): TlPackedSchema { +export function packTlSchema(schema: TlFullSchema, layer: number): TlPackedSchema { const ret: TlPackedSchema = { l: layer, e: schema.entries, diff --git a/packages/tl/scripts/utils.ts b/packages/tl/scripts/utils.ts index d081cf3a..85be884c 100644 --- a/packages/tl/scripts/utils.ts +++ b/packages/tl/scripts/utils.ts @@ -1,8 +1,4 @@ -export async function fetchRetry( - url: string, - params?: RequestInit, - retries = 5, -): Promise { +export async function fetchRetry(url: string, params?: RequestInit, retries = 5): Promise { while (true) { try { return await fetch(url, params).then((i) => i.text())