From b76463ccc0c346e4ad458b481f7956e502c468e4 Mon Sep 17 00:00:00 2001 From: alina sireneva Date: Sun, 18 Aug 2024 09:31:23 +0300 Subject: [PATCH] chore: enabled `isolatedDeclarations` --- e2e/node/ts/tests/packaging/tl-schema.ts | 2 - eslint.config.js | 8 +- packages/bun/src/client.ts | 3 +- packages/bun/src/sqlite/driver.ts | 2 +- packages/bun/src/sqlite/index.ts | 2 +- packages/bun/src/utils/crypto.ts | 2 +- packages/bun/src/utils/normalize-file.ts | 6 +- packages/bun/src/utils/tcp.ts | 2 +- packages/convert/src/utils/ip.ts | 4 +- packages/core/src/highlevel/base.ts | 9 +- packages/core/src/highlevel/client.ts | 1 - .../methods/chats/batched-queries.ts | 10 +- .../highlevel/methods/messages/send-common.ts | 8 +- .../src/highlevel/storage/service/peers.ts | 2 +- .../core/src/highlevel/storage/storage.ts | 6 +- .../highlevel/types/media/document-utils.ts | 2 +- .../core/src/highlevel/types/media/invoice.ts | 2 +- .../core/src/highlevel/types/media/photo.ts | 2 +- .../core/src/highlevel/types/media/poll.ts | 4 +- .../core/src/highlevel/types/media/sticker.ts | 2 +- .../core/src/highlevel/types/media/video.ts | 2 +- .../types/messages/input-message-id.ts | 5 +- .../types/messages/message-entity.ts | 4 +- .../src/highlevel/types/peers/chat-colors.ts | 2 +- .../highlevel/types/peers/chat-invite-link.ts | 2 +- .../src/highlevel/types/peers/forum-topic.ts | 2 +- .../highlevel/types/stories/all-stories.ts | 2 +- .../types/stories/interactive/input.ts | 2 +- .../core/src/highlevel/updates/manager.ts | 49 +++-- .../core/src/highlevel/utils/inline-utils.ts | 2 +- .../core/src/highlevel/utils/peer-utils.ts | 4 +- .../core/src/highlevel/utils/query-batcher.ts | 31 +-- .../core/src/highlevel/utils/stream-utils.ts | 5 +- .../core/src/highlevel/worker/app-config.ts | 2 +- packages/core/src/highlevel/worker/invoker.ts | 2 +- packages/core/src/highlevel/worker/port.ts | 42 ++-- packages/core/src/highlevel/worker/storage.ts | 18 +- packages/core/src/highlevel/worker/worker.ts | 2 +- packages/core/src/network/authorization.ts | 5 +- packages/core/src/network/client.ts | 4 +- packages/core/src/network/mtproto-session.ts | 30 +-- .../src/network/multi-session-connection.ts | 2 +- packages/core/src/network/network-manager.ts | 12 +- packages/core/src/network/server-salt.ts | 2 +- .../core/src/network/session-connection.ts | 4 +- .../src/network/transports/intermediate.ts | 2 +- .../core/src/network/transports/streamed.ts | 2 +- packages/core/src/storage/memory/driver.ts | 2 +- packages/core/src/storage/memory/index.ts | 10 +- .../storage/memory/repository/auth-keys.ts | 4 +- .../core/src/storage/memory/repository/kv.ts | 2 +- .../src/storage/memory/repository/peers.ts | 4 +- .../storage/memory/repository/ref-messages.ts | 4 +- packages/core/src/storage/sqlite/index.ts | 8 +- packages/core/src/storage/storage.ts | 15 +- packages/core/src/utils/bigint-utils.ts | 2 +- packages/core/src/utils/buffer-utils.ts | 4 +- packages/core/src/utils/crypto/abstract.ts | 4 +- packages/core/src/utils/deque.ts | 6 +- packages/core/src/utils/function-utils.ts | 7 +- packages/core/src/utils/links/bots.ts | 21 +- packages/core/src/utils/links/calls.ts | 5 +- packages/core/src/utils/links/chat.ts | 208 +++++++++--------- packages/core/src/utils/links/misc.ts | 7 +- packages/core/src/utils/links/proxy.ts | 9 +- packages/core/src/utils/links/stickers.ts | 5 +- packages/core/src/utils/links/user.ts | 7 +- packages/core/src/utils/logger.ts | 15 +- packages/core/src/utils/long-utils.ts | 10 +- packages/core/src/utils/lru-set.ts | 6 +- packages/create-bot/src/config.ts | 4 +- packages/create-bot/src/dependencies.ts | 4 +- packages/create-bot/src/package-manager.ts | 4 +- packages/create-bot/src/utils.ts | 2 +- packages/deno/src/sqlite/driver.ts | 2 +- packages/deno/src/sqlite/index.ts | 2 +- packages/deno/src/utils/crypto.ts | 2 +- packages/deno/src/utils/normalize-file.ts | 6 +- packages/deno/src/utils/tcp.ts | 2 +- .../src/context/business-message.ts | 36 +-- .../dispatcher/src/context/callback-query.ts | 16 +- .../dispatcher/src/context/inline-query.ts | 2 +- packages/dispatcher/src/context/message.ts | 55 +++-- packages/dispatcher/src/context/parse.ts | 51 ++++- packages/dispatcher/src/filters/bots.ts | 35 ++- packages/dispatcher/src/filters/message.ts | 65 ++++-- .../dispatcher/src/state/providers/memory.ts | 6 +- .../dispatcher/src/state/providers/sqlite.ts | 4 +- packages/dispatcher/src/state/service.ts | 9 +- packages/dispatcher/src/wizard.ts | 11 +- packages/file-id/src/types-inner.ts | 4 +- packages/http-proxy/index.ts | 2 +- packages/mtproxy/fake-tls.ts | 2 +- packages/node/src/client.ts | 3 +- .../node/src/common-internals-node/logging.ts | 8 +- packages/node/src/sqlite/driver.ts | 2 +- packages/node/src/sqlite/index.ts | 2 +- packages/node/src/utils/crypto.ts | 2 +- packages/node/src/utils/normalize-file.ts | 6 +- packages/node/src/utils/tcp.ts | 2 +- packages/node/src/utils/version.ts | 6 +- packages/socks-proxy/index.ts | 2 +- packages/test/src/client.ts | 16 +- packages/test/src/crypto.ts | 8 +- packages/test/src/platform.ts | 4 +- packages/test/src/platform.web.ts | 4 +- packages/test/src/schema.ts | 5 +- packages/test/src/storage.ts | 7 +- packages/test/src/storage/auth-keys.ts | 2 +- packages/test/src/storage/key-value.ts | 2 +- packages/test/src/storage/peers.ts | 2 +- packages/test/src/storage/ref-messages.ts | 2 +- packages/test/src/transport.ts | 2 +- packages/tl-runtime/src/reader.ts | 8 +- packages/tl-utils/src/codegen/reader.ts | 7 +- packages/tl-utils/src/codegen/writer.ts | 7 +- packages/tl-utils/src/utils.ts | 2 +- packages/tl/scripts/constants.ts | 16 +- packages/tl/scripts/documentation.ts | 4 +- .../tl/scripts/process-descriptions-yaml.ts | 2 +- packages/wasm/src/index.ts | 4 +- packages/web/src/idb/driver.ts | 2 +- packages/web/src/idb/index.ts | 10 +- packages/web/src/platform.ts | 2 +- packages/web/src/websocket.ts | 2 +- tsconfig.json | 2 +- 126 files changed, 676 insertions(+), 490 deletions(-) diff --git a/e2e/node/ts/tests/packaging/tl-schema.ts b/e2e/node/ts/tests/packaging/tl-schema.ts index 7c346140..529fa04b 100644 --- a/e2e/node/ts/tests/packaging/tl-schema.ts +++ b/e2e/node/ts/tests/packaging/tl-schema.ts @@ -28,12 +28,10 @@ describe('@mtcute/tl', () => { it('readers map works with TlBinaryReader', () => { const buf = p.hexDecode('4ca5e8dd7b00000000000000c801000000000000') - // eslint-disable-next-line const obj = TlBinaryReader.deserializeObject(__tlReaderMap, buf) expect(obj._).equal('inputPeerUser') expect(obj.userId).equal(123) - // eslint-disable-next-line expect(obj.accessHash.toString()).equal('456') }) diff --git a/eslint.config.js b/eslint.config.js index 38298990..efb0b8de 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -44,6 +44,12 @@ export default antfu({ SwitchCase: 1, VariableDeclarator: 1, }], + 'style/max-len': ['error', { + code: 120, + ignoreComments: true, + ignoreStrings: true, + ignoreTemplateLiterals: true, + }], 'curly': ['error', 'multi-line'], 'style/brace-style': ['error', '1tbs', { allowSingleLine: true }], 'node/prefer-global/process': ['error', 'always'], @@ -60,7 +66,7 @@ export default antfu({ 'ts/no-redeclare': 'off', 'eslint-comments/no-unlimited-disable': 'off', 'no-cond-assign': 'off', - 'ts/explicit-function-return-type': 'off', // todo: enable once we move to isolatedDeclarations + 'ts/explicit-function-return-type': 'off', 'no-labels': 'off', 'no-restricted-syntax': 'off', 'unicorn/no-new-array': 'off', diff --git a/packages/bun/src/client.ts b/packages/bun/src/client.ts index 97f1e85f..2349b5f7 100644 --- a/packages/bun/src/client.ts +++ b/packages/bun/src/client.ts @@ -1,5 +1,6 @@ import type { Interface as RlInterface } from 'node:readline' import { createInterface } from 'node:readline' +import type { Readable } from 'node:stream' import type { FileDownloadLocation, FileDownloadParameters, ITelegramStorageProvider, PartialOnly, User } from '@mtcute/core' import type { @@ -145,7 +146,7 @@ export class TelegramClient extends TelegramClientBase { return downloadToFile(this, filename, location, params) } - downloadAsNodeStream(location: FileDownloadLocation, params?: FileDownloadParameters | undefined) { + downloadAsNodeStream(location: FileDownloadLocation, params?: FileDownloadParameters | undefined): Readable { return downloadAsNodeStream(this, location, params) } } diff --git a/packages/bun/src/sqlite/driver.ts b/packages/bun/src/sqlite/driver.ts index ed9e703f..a9ce5c78 100644 --- a/packages/bun/src/sqlite/driver.ts +++ b/packages/bun/src/sqlite/driver.ts @@ -19,7 +19,7 @@ export interface SqliteStorageDriverOptions { export class SqliteStorageDriver extends BaseSqliteStorageDriver { constructor( readonly filename = ':memory:', - readonly params?: SqliteStorageDriverOptions, + readonly params?: SqliteStorageDriverOptions | undefined, ) { super() } diff --git a/packages/bun/src/sqlite/index.ts b/packages/bun/src/sqlite/index.ts index 1d5374f0..f4fbb33c 100644 --- a/packages/bun/src/sqlite/index.ts +++ b/packages/bun/src/sqlite/index.ts @@ -8,7 +8,7 @@ export { SqliteStorageDriver } from './driver.js' export class SqliteStorage extends BaseSqliteStorage { constructor( readonly filename = ':memory:', - readonly params?: SqliteStorageDriverOptions, + readonly params?: SqliteStorageDriverOptions | undefined, ) { super(new SqliteStorageDriver(filename, params)) } diff --git a/packages/bun/src/utils/crypto.ts b/packages/bun/src/utils/crypto.ts index 3d4a3904..7c79a07b 100644 --- a/packages/bun/src/utils/crypto.ts +++ b/packages/bun/src/utils/crypto.ts @@ -112,7 +112,7 @@ export class BunCryptoProvider extends BaseCryptoProvider implements ICryptoProv return gunzip(data) } - randomFill(buf: Uint8Array) { + randomFill(buf: Uint8Array): void { crypto.getRandomValues(buf) } } diff --git a/packages/bun/src/utils/normalize-file.ts b/packages/bun/src/utils/normalize-file.ts index 516b4fd6..540b6c15 100644 --- a/packages/bun/src/utils/normalize-file.ts +++ b/packages/bun/src/utils/normalize-file.ts @@ -11,7 +11,11 @@ function isBunFile(file: unknown): file is BunFile { return file instanceof Blob && 'name' in file && file.name.length > 0 } -export async function normalizeFile(file: UploadFileLike) { +export async function normalizeFile(file: UploadFileLike): Promise<{ + file: UploadFileLike + fileName?: string | undefined + fileSize?: number +} | null> { if (typeof file === 'string') { file = Bun.file(file) } diff --git a/packages/bun/src/utils/tcp.ts b/packages/bun/src/utils/tcp.ts index d0bedf57..c0a6f6cd 100644 --- a/packages/bun/src/utils/tcp.ts +++ b/packages/bun/src/utils/tcp.ts @@ -149,5 +149,5 @@ export abstract class BaseTcpTransport extends EventEmitter implements ITelegram } export class TcpTransport extends BaseTcpTransport { - _packetCodec = new IntermediatePacketCodec() + _packetCodec: IntermediatePacketCodec = new IntermediatePacketCodec() } diff --git a/packages/convert/src/utils/ip.ts b/packages/convert/src/utils/ip.ts index 7776e29a..e73b199b 100644 --- a/packages/convert/src/utils/ip.ts +++ b/packages/convert/src/utils/ip.ts @@ -20,7 +20,7 @@ export function parseIpFromBytes(data: Uint8Array): string { throw new MtArgumentError('Invalid IP address length') } -export function serializeIpv4ToBytes(ip: string, buf: Uint8Array) { +export function serializeIpv4ToBytes(ip: string, buf: Uint8Array): void { const parts = ip.split('.') if (parts.length !== 4) { @@ -33,7 +33,7 @@ export function serializeIpv4ToBytes(ip: string, buf: Uint8Array) { buf[3] = Number(parts[3]) } -export function serializeIpv6ToBytes(ip: string, buf: Uint8Array) { +export function serializeIpv6ToBytes(ip: string, buf: Uint8Array): void { const parts = ip.split(':') if (parts.length !== 8) { diff --git a/packages/core/src/highlevel/base.ts b/packages/core/src/highlevel/base.ts index c04052b2..5ed8520e 100644 --- a/packages/core/src/highlevel/base.ts +++ b/packages/core/src/highlevel/base.ts @@ -94,7 +94,7 @@ export class BaseTelegramClient implements ITelegramClient { }) } - readonly appConfig = new AppConfigManager(this) + readonly appConfig: AppConfigManager = new AppConfigManager(this) private _prepare = asyncResettable(async () => { await this.mt.prepare() @@ -115,7 +115,7 @@ export class BaseTelegramClient implements ITelegramClient { * * Call {@link connect} to actually connect. */ - prepare() { + prepare(): Promise { return this._prepare.run() } @@ -327,7 +327,10 @@ export class BaseTelegramClient implements ITelegramClient { this._connectionStateHandler = handler } - async getApiCrenetials() { + async getApiCrenetials(): Promise<{ + id: number + hash: string + }> { return { id: this.params.apiId, hash: this.params.apiHash, diff --git a/packages/core/src/highlevel/client.ts b/packages/core/src/highlevel/client.ts index 53bb083c..c4f43a21 100644 --- a/packages/core/src/highlevel/client.ts +++ b/packages/core/src/highlevel/client.ts @@ -519,7 +519,6 @@ export interface TelegramClient extends ITelegramClient { */ on(name: 'delete_business_message', handler: ((upd: DeleteBusinessMessageUpdate) => void)): this - // eslint-disable-next-line ts/no-explicit-any on(name: string, handler: (...args: any[]) => void): this /** diff --git a/packages/core/src/highlevel/methods/chats/batched-queries.ts b/packages/core/src/highlevel/methods/chats/batched-queries.ts index 24c9fb49..4732be15 100644 --- a/packages/core/src/highlevel/methods/chats/batched-queries.ts +++ b/packages/core/src/highlevel/methods/chats/batched-queries.ts @@ -9,10 +9,11 @@ import { toInputChannel, toInputUser, } from '../../utils/peer-utils.js' +import type { BatchedQuery } from '../../utils/query-batcher.js' import { batchedQuery } from '../../utils/query-batcher.js' /** @internal */ -export const _getUsersBatched = batchedQuery({ +export const _getUsersBatched: BatchedQuery = batchedQuery({ fetch: (client, items) => client .call({ @@ -63,7 +64,7 @@ export const _getUsersBatched = batchedQuery({ +export const _getChatsBatched: BatchedQuery = batchedQuery({ fetch: (client, items) => client .call({ @@ -78,7 +79,10 @@ export const _getChatsBatched = batchedQuery({ }) /** @internal */ -export const _getChannelsBatched = batchedQuery({ +export const _getChannelsBatched: BatchedQuery< + tl.TypeInputChannel, + tl.RawChannel | tl.RawChannelForbidden +> = batchedQuery({ fetch: (client, items) => client .call({ diff --git a/packages/core/src/highlevel/methods/messages/send-common.ts b/packages/core/src/highlevel/methods/messages/send-common.ts index 21df5daf..76a42cb6 100644 --- a/packages/core/src/highlevel/methods/messages/send-common.ts +++ b/packages/core/src/highlevel/methods/messages/send-common.ts @@ -156,7 +156,13 @@ export async function _processCommonSendParameters( client: ITelegramClient, chatId: InputPeerLike, params: CommonSendParams, -) { +): Promise<{ + peer: tl.TypeInputPeer + replyTo: tl.TypeInputReplyTo | undefined + scheduleDate: number | undefined + quickReplyShortcut: tl.TypeInputQuickReplyShortcut | undefined + chainId: string + }> { let peer = await resolvePeer(client, chatId) let replyTo = normalizeMessageId(params.replyTo) diff --git a/packages/core/src/highlevel/storage/service/peers.ts b/packages/core/src/highlevel/storage/service/peers.ts index c5fc1b06..4ede9210 100644 --- a/packages/core/src/highlevel/storage/service/peers.ts +++ b/packages/core/src/highlevel/storage/service/peers.ts @@ -62,7 +62,7 @@ export class PeersService extends BaseService { this._cache = new LruMap(options.cacheSize ?? 100) } - async updatePeersFrom(obj: tl.TlObject | tl.TlObject[]) { + async updatePeersFrom(obj: tl.TlObject | tl.TlObject[]): Promise { let count = 0 for (const peer of getAllPeersFrom(obj)) { diff --git a/packages/core/src/highlevel/storage/storage.ts b/packages/core/src/highlevel/storage/storage.ts index 70864370..3c330e55 100644 --- a/packages/core/src/highlevel/storage/storage.ts +++ b/packages/core/src/highlevel/storage/storage.ts @@ -23,9 +23,9 @@ export interface TelegramStorageManagerExtraOptions { export class TelegramStorageManager { private provider - readonly updates + readonly updates: UpdatesStateService readonly self: PublicPart - readonly refMsgs + readonly refMsgs: RefMessagesService readonly peers: PublicPart constructor( @@ -56,7 +56,7 @@ export class TelegramStorageManager { ) } - async clear(withAuthKeys = false) { + async clear(withAuthKeys = false): Promise { await this.provider.peers.deleteAll() await this.provider.refMessages.deleteAll() await this.mt.clear(withAuthKeys) diff --git a/packages/core/src/highlevel/types/media/document-utils.ts b/packages/core/src/highlevel/types/media/document-utils.ts index 150d53b9..883537a3 100644 --- a/packages/core/src/highlevel/types/media/document-utils.ts +++ b/packages/core/src/highlevel/types/media/document-utils.ts @@ -9,7 +9,7 @@ import { Voice } from './voice.js' export type ParsedDocument = Sticker | Voice | Audio | Video | Document /** @internal */ -export function parseSticker(doc: tl.RawDocument) { +export function parseSticker(doc: tl.RawDocument): Sticker | undefined { const stickerAttr = doc.attributes.find( a => a._ === 'documentAttributeSticker' || a._ === 'documentAttributeCustomEmoji', ) diff --git a/packages/core/src/highlevel/types/media/invoice.ts b/packages/core/src/highlevel/types/media/invoice.ts index b61aaca5..2e6c8168 100644 --- a/packages/core/src/highlevel/types/media/invoice.ts +++ b/packages/core/src/highlevel/types/media/invoice.ts @@ -24,7 +24,7 @@ export class Invoice { constructor( readonly raw: tl.RawMessageMediaInvoice, - private readonly _extendedMedia?: MessageMedia, + private readonly _extendedMedia?: MessageMedia | undefined, ) {} /** diff --git a/packages/core/src/highlevel/types/media/photo.ts b/packages/core/src/highlevel/types/media/photo.ts index 9287295b..160e464e 100644 --- a/packages/core/src/highlevel/types/media/photo.ts +++ b/packages/core/src/highlevel/types/media/photo.ts @@ -23,7 +23,7 @@ export class Photo extends FileLocation { constructor( readonly raw: tl.RawPhoto, - readonly media?: tl.RawMessageMediaPhoto, + readonly media?: tl.RawMessageMediaPhoto | undefined, ) { const location = { _: 'inputPhotoFileLocation', diff --git a/packages/core/src/highlevel/types/media/poll.ts b/packages/core/src/highlevel/types/media/poll.ts index 86e37737..472f26d6 100644 --- a/packages/core/src/highlevel/types/media/poll.ts +++ b/packages/core/src/highlevel/types/media/poll.ts @@ -9,7 +9,7 @@ import type { PeersIndex } from '../peers/peers-index.js' export class PollAnswer { constructor( readonly raw: tl.TypePollAnswer, - readonly result?: tl.TypePollAnswerVoters, + readonly result?: tl.RawPollAnswerVoters | undefined, ) {} /** @@ -71,7 +71,7 @@ export class Poll { constructor( readonly raw: tl.TypePoll, readonly _peers: PeersIndex, - readonly results?: tl.TypePollResults, + readonly results?: tl.RawPollResults | undefined, ) {} /** diff --git a/packages/core/src/highlevel/types/media/sticker.ts b/packages/core/src/highlevel/types/media/sticker.ts index abe74af3..692940d8 100644 --- a/packages/core/src/highlevel/types/media/sticker.ts +++ b/packages/core/src/highlevel/types/media/sticker.ts @@ -72,7 +72,7 @@ export class Sticker extends RawDocument { constructor( doc: tl.RawDocument, readonly attr: tl.RawDocumentAttributeSticker | tl.RawDocumentAttributeCustomEmoji, - readonly attr2?: tl.RawDocumentAttributeImageSize | tl.RawDocumentAttributeVideo, + readonly attr2?: tl.RawDocumentAttributeImageSize | tl.RawDocumentAttributeVideo | undefined, ) { super(doc) } diff --git a/packages/core/src/highlevel/types/media/video.ts b/packages/core/src/highlevel/types/media/video.ts index b094e582..718fcd05 100644 --- a/packages/core/src/highlevel/types/media/video.ts +++ b/packages/core/src/highlevel/types/media/video.ts @@ -24,7 +24,7 @@ export class Video extends RawDocument { constructor( doc: tl.RawDocument, readonly attr: tl.RawDocumentAttributeVideo | tl.RawDocumentAttributeImageSize, - readonly media?: tl.RawMessageMediaDocument, + readonly media?: tl.RawMessageMediaDocument | undefined, ) { super(doc) } diff --git a/packages/core/src/highlevel/types/messages/input-message-id.ts b/packages/core/src/highlevel/types/messages/input-message-id.ts index 541fe7dd..f11451b8 100644 --- a/packages/core/src/highlevel/types/messages/input-message-id.ts +++ b/packages/core/src/highlevel/types/messages/input-message-id.ts @@ -13,7 +13,10 @@ export type InputMessageId = { chatId: InputPeerLike, message: number } | { mess export type OmitInputMessageId = Omit /** @internal */ -export function normalizeInputMessageId(id: InputMessageId) { +export function normalizeInputMessageId(id: InputMessageId): { + chatId: InputPeerLike + message: number +} { if ('chatId' in id) return id return { chatId: id.message.chat.inputPeer, message: id.message.id } diff --git a/packages/core/src/highlevel/types/messages/message-entity.ts b/packages/core/src/highlevel/types/messages/message-entity.ts index c2af3978..89d8a1a3 100644 --- a/packages/core/src/highlevel/types/messages/message-entity.ts +++ b/packages/core/src/highlevel/types/messages/message-entity.ts @@ -67,7 +67,7 @@ export class MessageEntity { * * Since JS strings are UTF-16, you can use this as-is */ - get offset() { + get offset(): number { return this.raw.offset } @@ -76,7 +76,7 @@ export class MessageEntity { * * Since JS strings are UTF-16, you can use this as-is */ - get length() { + get length(): number { return this.raw.length } diff --git a/packages/core/src/highlevel/types/peers/chat-colors.ts b/packages/core/src/highlevel/types/peers/chat-colors.ts index bcf2c60f..c6ea8123 100644 --- a/packages/core/src/highlevel/types/peers/chat-colors.ts +++ b/packages/core/src/highlevel/types/peers/chat-colors.ts @@ -8,7 +8,7 @@ import { makeInspectable } from '../../utils/inspectable.js' export class ChatColors { constructor( private readonly _peerId: number, - readonly raw?: tl.RawPeerColor, + readonly raw?: tl.RawPeerColor | undefined, ) {} /** diff --git a/packages/core/src/highlevel/types/peers/chat-invite-link.ts b/packages/core/src/highlevel/types/peers/chat-invite-link.ts index 4e88c744..55617fe8 100644 --- a/packages/core/src/highlevel/types/peers/chat-invite-link.ts +++ b/packages/core/src/highlevel/types/peers/chat-invite-link.ts @@ -16,7 +16,7 @@ export class ChatInviteLink { constructor( raw: tl.TypeExportedChatInvite, - readonly _peers?: PeersIndex, + readonly _peers?: PeersIndex | undefined, ) { assertTypeIsNot('ChatInviteLink', raw, 'chatInvitePublicJoinRequests') diff --git a/packages/core/src/highlevel/types/peers/forum-topic.ts b/packages/core/src/highlevel/types/peers/forum-topic.ts index 270f5b1f..3b543b84 100644 --- a/packages/core/src/highlevel/types/peers/forum-topic.ts +++ b/packages/core/src/highlevel/types/peers/forum-topic.ts @@ -21,7 +21,7 @@ export class ForumTopic { constructor( readonly raw: tl.RawForumTopic, readonly _peers: PeersIndex, - readonly _messages?: Map, + readonly _messages?: Map | undefined, ) {} static parseTlForumTopics(topics: tl.messages.TypeForumTopics): ForumTopic[] { diff --git a/packages/core/src/highlevel/types/stories/all-stories.ts b/packages/core/src/highlevel/types/stories/all-stories.ts index 948da2aa..3935d167 100644 --- a/packages/core/src/highlevel/types/stories/all-stories.ts +++ b/packages/core/src/highlevel/types/stories/all-stories.ts @@ -14,7 +14,7 @@ import { StoriesStealthMode } from './stealth-mode.js' */ export class AllStories { /** Peers index */ - readonly _peers + readonly _peers: PeersIndex constructor( /** Raw TL object */ readonly raw: tl.stories.RawAllStories, diff --git a/packages/core/src/highlevel/types/stories/interactive/input.ts b/packages/core/src/highlevel/types/stories/interactive/input.ts index 56a2ceb7..3b11c9ce 100644 --- a/packages/core/src/highlevel/types/stories/interactive/input.ts +++ b/packages/core/src/highlevel/types/stories/interactive/input.ts @@ -18,7 +18,7 @@ import { normalizeInputReaction } from '../../reactions/index.js' export class StoryElement { private constructor(private _position: tl.RawMediaAreaCoordinates) {} - static at(params: { x: number, y: number, width: number, height: number, rotation?: number }) { + static at(params: { x: number, y: number, width: number, height: number, rotation?: number }): StoryElement { return new StoryElement({ _: 'mediaAreaCoordinates', x: params.x, diff --git a/packages/core/src/highlevel/updates/manager.ts b/packages/core/src/highlevel/updates/manager.ts index 8d80e108..716bc7cf 100644 --- a/packages/core/src/highlevel/updates/manager.ts +++ b/packages/core/src/highlevel/updates/manager.ts @@ -3,6 +3,9 @@ import { tl } from '@mtcute/tl' import { MtArgumentError } from '../../types/errors.js' import type { MaybePromise } from '../../types/utils.js' import { assertNever } from '../../types/utils.js' +import type { + Logger, +} from '../../utils/index.js' import { AsyncLock, ConditionVariable, @@ -89,26 +92,32 @@ const UPDATES_TOO_LONG = { _: 'updatesTooLong' } as const // todo: fix docs export class UpdatesManager { updatesLoopActive = false - updatesLoopCv = new ConditionVariable() + updatesLoopCv: ConditionVariable = new ConditionVariable() - postponedTimer = new EarlyTimer() + postponedTimer: EarlyTimer = new EarlyTimer() hasTimedoutPostponed = false - pendingUpdateContainers = new SortedLinkedList((a, b) => a.seqStart - b.seqStart) - pendingPtsUpdates = new SortedLinkedList((a, b) => a.ptsBefore! - b.ptsBefore!) - pendingPtsUpdatesPostponed = new SortedLinkedList((a, b) => a.ptsBefore! - b.ptsBefore!) - pendingQtsUpdates = new SortedLinkedList((a, b) => a.qtsBefore! - b.qtsBefore!) - pendingQtsUpdatesPostponed = new SortedLinkedList((a, b) => a.qtsBefore! - b.qtsBefore!) - pendingUnorderedUpdates = new Deque() + pendingUpdateContainers: SortedLinkedList + = new SortedLinkedList((a, b) => a.seqStart - b.seqStart) - noDispatchEnabled + pendingPtsUpdates: SortedLinkedList = new SortedLinkedList((a, b) => a.ptsBefore! - b.ptsBefore!) + pendingPtsUpdatesPostponed: SortedLinkedList + = new SortedLinkedList((a, b) => a.ptsBefore! - b.ptsBefore!) + + pendingQtsUpdates: SortedLinkedList = new SortedLinkedList((a, b) => a.qtsBefore! - b.qtsBefore!) + pendingQtsUpdatesPostponed: SortedLinkedList + = new SortedLinkedList((a, b) => a.qtsBefore! - b.qtsBefore!) + + pendingUnorderedUpdates: Deque = new Deque() + + noDispatchEnabled: boolean // channel id or 0 => msg id - noDispatchMsg = new Map>() + noDispatchMsg: Map> = new Map() // channel id or 0 => pts - noDispatchPts = new Map>() - noDispatchQts = new Set() + noDispatchPts: Map> = new Map() + noDispatchQts: Set = new Set() - lock = new AsyncLock() + lock: AsyncLock = new AsyncLock() // rpsIncoming?: RpsMeter // rpsProcessing?: RpsMeter @@ -129,14 +138,14 @@ export class UpdatesManager { // whether to catch up channels from the locally stored pts catchingUp = false - catchUpOnStart + catchUpOnStart: boolean - cpts = new Map() - cptsMod = new Map() - channelDiffTimeouts = new Map() - channelsOpened = new Map() + cpts: Map = new Map() + cptsMod: Map = new Map() + channelDiffTimeouts: Map = new Map() + channelsOpened: Map = new Map() - log + log: Logger private _handler: RawUpdateHandler = () => {} private _onCatchingUp: (catchingUp: boolean) => void = () => {} @@ -189,7 +198,7 @@ export class UpdatesManager { this._onCatchingUp = handler } - destroy() { + destroy(): void { this.stopLoop() } diff --git a/packages/core/src/highlevel/utils/inline-utils.ts b/packages/core/src/highlevel/utils/inline-utils.ts index cf206c43..fb57f448 100644 --- a/packages/core/src/highlevel/utils/inline-utils.ts +++ b/packages/core/src/highlevel/utils/inline-utils.ts @@ -60,7 +60,7 @@ export function encodeInlineMessageId(id: tl.TypeInputBotInlineMessageID): strin return getPlatform().base64Encode(writer.result(), true) } -export function normalizeInlineId(id: string | tl.TypeInputBotInlineMessageID) { +export function normalizeInlineId(id: string | tl.TypeInputBotInlineMessageID): tl.TypeInputBotInlineMessageID { if (typeof id === 'string') { return parseInlineMessageId(id) } diff --git a/packages/core/src/highlevel/utils/peer-utils.ts b/packages/core/src/highlevel/utils/peer-utils.ts index 10f60b1f..185c4eec 100644 --- a/packages/core/src/highlevel/utils/peer-utils.ts +++ b/packages/core/src/highlevel/utils/peer-utils.ts @@ -4,7 +4,7 @@ import { assertNever } from '../../types/utils.js' import { MtInvalidPeerTypeError } from '../types/errors.js' import type { InputPeerLike } from '../types/peers/index.js' -export const INVITE_LINK_REGEX +export const INVITE_LINK_REGEX: RegExp = /^(?:https?:\/\/)?(?:www\.)?t(?:elegram)?\.(?:org|me|dog)\/(?:joinchat\/|\+)([\w-]+)$/i // helpers to convert result of `resolvePeer` function @@ -145,7 +145,7 @@ export function inputPeerToPeer(inp: tl.TypeInputPeer): tl.TypePeer { } } -export function extractUsernames(obj: tl.RawUser | tl.RawChannel) { +export function extractUsernames(obj: tl.RawUser | tl.RawChannel): string[] { if (obj.usernames?.length) return obj.usernames.map(x => x.username.toLowerCase()) if (obj.username) return [obj.username.toLowerCase()] diff --git a/packages/core/src/highlevel/utils/query-batcher.ts b/packages/core/src/highlevel/utils/query-batcher.ts index 1bc63e6c..cdbcac84 100644 --- a/packages/core/src/highlevel/utils/query-batcher.ts +++ b/packages/core/src/highlevel/utils/query-batcher.ts @@ -4,14 +4,15 @@ import type { ITelegramClient } from '../client.types.js' type Resolve = (value: T | PromiseLike) => void type Reject = (err?: unknown) => void -type WaitersMap = Map, Reject][]> -interface InternalState { - waiters: WaitersMap - fetchingKeys: Set +type WaitersMap = Map, Reject][]> +interface InternalState { + waiters: WaitersMap + fetchingKeys: Set retryQueue: Deque numRunning: number } +export type BatchedQuery = (client: ITelegramClient, item: T) => Promise // todo: should it be MtClient? /** @@ -23,7 +24,7 @@ interface InternalState { * - "key" - unique identifier of the item, which should be deriveable from both input and output. * used for matching input and output items and deduplicating them. */ -export function batchedQuery(params: { +export function batchedQuery(params: { /** * Fetcher function, taking an array of input items and returning an array of output items. * @@ -33,9 +34,9 @@ export function batchedQuery(params: { fetch: (client: ITelegramClient, items: T[]) => Promise /** Key derivation function for input items */ - inputKey: (item: T, client: ITelegramClient) => K + inputKey: (item: T, client: ITelegramClient) => string | number /** Key derivation function for output items */ - outputKey: (item: U, client: ITelegramClient) => K + outputKey: (item: U, client: ITelegramClient) => string | number /** * Maximum number of items to be passed to the `fetcher` function at once. @@ -64,13 +65,13 @@ export function batchedQuery(params: { * or an array of items for which the query should be retried (waiters for other items will throw `err`). */ retrySingleOnError?: (items: T[], err: unknown) => boolean | T[] -}): (client: ITelegramClient, item: T) => Promise { +}): BatchedQuery { const { inputKey, outputKey, fetch, maxBatchSize = Infinity, maxConcurrent = 1, retrySingleOnError } = params const symbol = Symbol('batchedQueryState') function getState(client_: ITelegramClient) { - const client = client_ as { [symbol]?: InternalState } + const client = client_ as { [symbol]?: InternalState } if (!client[symbol]) { client[symbol] = { @@ -84,7 +85,7 @@ export function batchedQuery(params: { return client[symbol] } - function addWaiter(client: ITelegramClient, waiters: WaitersMap, item: T) { + function addWaiter(client: ITelegramClient, waiters: WaitersMap, item: T) { const key = inputKey(item, client) let arr = waiters.get(key) @@ -99,7 +100,7 @@ export function batchedQuery(params: { }) } - function popWaiters(waiters: WaitersMap, key: K) { + function popWaiters(waiters: WaitersMap, key: string | number) { const arr = waiters.get(key) if (!arr) return [] @@ -108,19 +109,19 @@ export function batchedQuery(params: { return arr } - function startLoops(client: ITelegramClient, state: InternalState) { + function startLoops(client: ITelegramClient, state: InternalState) { for (let i = state.numRunning; i <= maxConcurrent; i++) { processPending(client, state) } } - function processPending(client: ITelegramClient, state: InternalState) { + function processPending(client: ITelegramClient, state: InternalState) { const { waiters, fetchingKeys, retryQueue } = state if (state.numRunning >= maxConcurrent) return const request: T[] = [] - const requestKeys: K[] = [] + const requestKeys: (string | number)[] = [] let isRetryRequest = false if (retryQueue.length > 0) { @@ -152,7 +153,7 @@ export function batchedQuery(params: { // eslint-disable-next-line ts/no-floating-promises fetch(client, request) .then((res) => { - const receivedKeys = new Set() + const receivedKeys = new Set() for (const it of res) { const key = outputKey(it, client) diff --git a/packages/core/src/highlevel/utils/stream-utils.ts b/packages/core/src/highlevel/utils/stream-utils.ts index 971630a3..123347f8 100644 --- a/packages/core/src/highlevel/utils/stream-utils.ts +++ b/packages/core/src/highlevel/utils/stream-utils.ts @@ -24,7 +24,10 @@ export async function streamToBuffer(stream: ReadableStream): Promis return concatBuffers(chunks) } -export function createChunkedReader(stream: ReadableStream, chunkSize: number) { +export function createChunkedReader(stream: ReadableStream, chunkSize: number): { + ended: () => boolean + read: () => Promise +} { const reader = stream.getReader() const lock = new AsyncLock() diff --git a/packages/core/src/highlevel/worker/app-config.ts b/packages/core/src/highlevel/worker/app-config.ts index a09571f2..79e67ff9 100644 --- a/packages/core/src/highlevel/worker/app-config.ts +++ b/packages/core/src/highlevel/worker/app-config.ts @@ -5,7 +5,7 @@ import type { WorkerInvoker } from './invoker.js' export class AppConfigManagerProxy implements PublicPart { readonly get: AppConfigManager['get'] - readonly getField + readonly getField: AppConfigManager['getField'] constructor(readonly invoker: WorkerInvoker) { const bind = invoker.makeBinder('app-config') diff --git a/packages/core/src/highlevel/worker/invoker.ts b/packages/core/src/highlevel/worker/invoker.ts index f6bee994..fcdc566c 100644 --- a/packages/core/src/highlevel/worker/invoker.ts +++ b/packages/core/src/highlevel/worker/invoker.ts @@ -57,7 +57,7 @@ export class WorkerInvoker { return this._invoke(target, method, args, false, abortSignal) as Promise } - handleResult(msg: Extract) { + handleResult(msg: Extract): void { const promise = this._pending.get(msg.id) if (!promise) return diff --git a/packages/core/src/highlevel/worker/port.ts b/packages/core/src/highlevel/worker/port.ts index 6bf90e23..2f90d3ff 100644 --- a/packages/core/src/highlevel/worker/port.ts +++ b/packages/core/src/highlevel/worker/port.ts @@ -18,36 +18,36 @@ export interface TelegramWorkerPortOptions { } export abstract class TelegramWorkerPort implements ITelegramClient { - readonly log + readonly log: LogManager private _connection private _invoker - readonly storage - readonly appConfig + readonly storage: TelegramStorageProxy + readonly appConfig: AppConfigManagerProxy // bound methods - readonly prepare + readonly prepare: ITelegramClient['prepare'] private _connect - readonly close - readonly notifyLoggedIn - readonly notifyLoggedOut - readonly notifyChannelOpened - readonly notifyChannelClosed - readonly importSession - readonly exportSession - readonly handleClientUpdate - readonly getApiCrenetials - readonly getPoolSize - readonly getPrimaryDcId - readonly changePrimaryDc - readonly computeSrpParams - readonly computeNewPasswordHash - readonly startUpdatesLoop - readonly stopUpdatesLoop + readonly close: ITelegramClient['close'] + readonly notifyLoggedIn: ITelegramClient['notifyLoggedIn'] + readonly notifyLoggedOut: ITelegramClient['notifyLoggedOut'] + readonly notifyChannelOpened: ITelegramClient['notifyChannelOpened'] + readonly notifyChannelClosed: ITelegramClient['notifyChannelClosed'] + readonly importSession: ITelegramClient['importSession'] + readonly exportSession: ITelegramClient['exportSession'] + readonly handleClientUpdate: ITelegramClient['handleClientUpdate'] + readonly getApiCrenetials: ITelegramClient['getApiCrenetials'] + readonly getPoolSize: ITelegramClient['getPoolSize'] + readonly getPrimaryDcId: ITelegramClient['getPrimaryDcId'] + readonly changePrimaryDc: ITelegramClient['changePrimaryDc'] + readonly computeSrpParams: ITelegramClient['computeSrpParams'] + readonly computeNewPasswordHash: ITelegramClient['computeNewPasswordHash'] + readonly startUpdatesLoop: ITelegramClient['startUpdatesLoop'] + readonly stopUpdatesLoop: ITelegramClient['stopUpdatesLoop'] private _abortController = new AbortController() - readonly stopSignal = this._abortController.signal + readonly stopSignal: AbortSignal = this._abortController.signal constructor(readonly options: TelegramWorkerPortOptions) { this.log = new LogManager('worker') diff --git a/packages/core/src/highlevel/worker/storage.ts b/packages/core/src/highlevel/worker/storage.ts index 3170a2d3..ac2475b1 100644 --- a/packages/core/src/highlevel/worker/storage.ts +++ b/packages/core/src/highlevel/worker/storage.ts @@ -60,12 +60,12 @@ class CurrentUserServiceProxy implements PublicPart { } class PeersServiceProxy implements PublicPart { - readonly updatePeersFrom - readonly store - readonly getById - readonly getByPhone - readonly getByUsername - readonly getCompleteById + readonly updatePeersFrom: PeersService['updatePeersFrom'] + readonly store: PeersService['store'] + readonly getById: PeersService['getById'] + readonly getByPhone: PeersService['getByPhone'] + readonly getByUsername: PeersService['getByUsername'] + readonly getCompleteById: PeersService['getCompleteById'] constructor(private _invoker: WorkerInvoker) { const bind = this._invoker.makeBinder('storage-peers') @@ -80,10 +80,10 @@ class PeersServiceProxy implements PublicPart { } export class TelegramStorageProxy implements PublicPart { - readonly self - readonly peers + readonly self: CurrentUserServiceProxy + readonly peers: PeersServiceProxy - readonly clear + readonly clear: TelegramStorageManager['clear'] constructor(private _invoker: WorkerInvoker) { const bind = this._invoker.makeBinder('storage') diff --git a/packages/core/src/highlevel/worker/worker.ts b/packages/core/src/highlevel/worker/worker.ts index 314d4e51..c2acaa55 100644 --- a/packages/core/src/highlevel/worker/worker.ts +++ b/packages/core/src/highlevel/worker/worker.ts @@ -24,7 +24,7 @@ export abstract class TelegramWorker { abstract registerWorker(handler: WorkerMessageHandler): RespondFn - readonly pendingAborts = new Map() + readonly pendingAborts: Map = new Map() constructor(readonly params: TelegramWorkerOptions) { this.broadcast = this.registerWorker((message, respond) => { diff --git a/packages/core/src/network/authorization.ts b/packages/core/src/network/authorization.ts index 45ae0b86..cf11d21e 100644 --- a/packages/core/src/network/authorization.ts +++ b/packages/core/src/network/authorization.ts @@ -20,9 +20,8 @@ import type { SessionConnection } from './session-connection.js' // see https://core.telegram.org/mtproto/security_guidelines // const DH_SAFETY_RANGE = bigInt[2].pow(2048 - 64) const DH_SAFETY_RANGE = 2n ** (2048n - 64n) -const KNOWN_DH_PRIME - - = 0xC71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5Bn +// eslint-disable-next-line style/max-len +const KNOWN_DH_PRIME = 0xC71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5Bn const TWO_POW_2047 = 2n ** 2047n const TWO_POW_2048 = 2n ** 2048n diff --git a/packages/core/src/network/client.ts b/packages/core/src/network/client.ts index 1cb2a76a..3720ec72 100644 --- a/packages/core/src/network/client.ts +++ b/packages/core/src/network/client.ts @@ -204,7 +204,7 @@ export class MtClient extends EventEmitter { /** TL writers map used by the client */ readonly _writerMap: TlWriterMap - readonly _config = new ConfigManager(async () => { + readonly _config: ConfigManager = new ConfigManager(async () => { const res = await this.call({ _: 'help.getConfig' }) if (isTlRpcError(res)) throw new Error(`Failed to get config: ${res.errorMessage}`) @@ -313,7 +313,7 @@ export class MtClient extends EventEmitter { * * Call {@link connect} to actually connect. */ - prepare() { + prepare(): Promise { return this._prepare.run() } diff --git a/packages/core/src/network/mtproto-session.ts b/packages/core/src/network/mtproto-session.ts index 8365f39e..72dedcd1 100644 --- a/packages/core/src/network/mtproto-session.ts +++ b/packages/core/src/network/mtproto-session.ts @@ -92,40 +92,40 @@ export type PendingMessage = * all the relevant state */ export class MtprotoSession { - _sessionId = randomLong() + _sessionId: Long = randomLong() _authKey: AuthKey _authKeyTemp: AuthKey _authKeyTempSecondary: AuthKey _timeOffset = 0 - _lastMessageId = Long.ZERO + _lastMessageId: Long = Long.ZERO _seqNo = 0 /// state /// // recent msg ids - recentOutgoingMsgIds = new LruSet(1000, true) - recentIncomingMsgIds = new LruSet(1000, true) + recentOutgoingMsgIds: LruSet = new LruSet(1000, true) + recentIncomingMsgIds: LruSet = new LruSet(1000, true) // queues - queuedRpc = new Deque() + queuedRpc: Deque = new Deque() queuedAcks: Long[] = [] queuedStateReq: Long[] = [] queuedResendReq: Long[] = [] queuedCancelReq: Long[] = [] - getStateSchedule = new SortedArray([], (a, b) => a.getState! - b.getState!) + getStateSchedule: SortedArray = new SortedArray([], (a, b) => a.getState! - b.getState!) - chains = new Map() - chainsPendingFails = new Map>() + chains: Map = new Map() + chainsPendingFails: Map> = new Map() // requests info - pendingMessages = new LongMap() - destroySessionIdToMsgId = new LongMap() + pendingMessages: LongMap = new LongMap() + destroySessionIdToMsgId: LongMap = new LongMap() - lastPingRtt = Number.NaN + lastPingRtt: number = Number.NaN lastPingTime = 0 - lastPingMsgId = Long.ZERO - lastSessionCreatedUid = Long.ZERO + lastPingMsgId: Long = Long.ZERO + lastSessionCreatedUid: Long = Long.ZERO initConnectionCalled = false authorizationPending = false @@ -176,7 +176,7 @@ export class MtprotoSession { this._authKeyTempSecondary.reset() } - updateTimeOffset(offset: number) { + updateTimeOffset(offset: number): void { this.log.debug('time offset updated: %d', offset) this._timeOffset = offset // lastMessageId was generated with (potentially) wrong time @@ -330,7 +330,7 @@ export class MtprotoSession { return messageId } - onTransportFlood(callback: () => void) { + onTransportFlood(callback: () => void): number | undefined { if (this.current429Timeout) return // already waiting // all active queries must be resent after a timeout diff --git a/packages/core/src/network/multi-session-connection.ts b/packages/core/src/network/multi-session-connection.ts index c0d93b65..5269412e 100644 --- a/packages/core/src/network/multi-session-connection.ts +++ b/packages/core/src/network/multi-session-connection.ts @@ -32,7 +32,7 @@ export class MultiSessionConnection extends EventEmitter { protected _connections: SessionConnection[] = [] - setCount(count: number, connect = this.params.isMainConnection): void { + setCount(count: number, connect: boolean = this.params.isMainConnection): void { this._count = count this._updateConnections(connect) diff --git a/packages/core/src/network/network-manager.ts b/packages/core/src/network/network-manager.ts index 9dbe0cf9..24daac24 100644 --- a/packages/core/src/network/network-manager.ts +++ b/packages/core/src/network/network-manager.ts @@ -456,7 +456,7 @@ export class DcConnectionManager { this.main.setCount(count) } - async destroy() { + async destroy(): Promise { await this.main.destroy() await this.upload.destroy() await this.download.destroy() @@ -469,15 +469,15 @@ export class DcConnectionManager { * Class that manages all connections to Telegram servers. */ export class NetworkManager { - readonly _log - readonly _storage + readonly _log: Logger + readonly _storage: StorageManager readonly _initConnectionParams: tl.RawInitConnectionRequest readonly _transportFactory: TransportFactory readonly _reconnectionStrategy: ReconnectionStrategy readonly _connectionCount: ConnectionCountDelegate - protected readonly _dcConnections = new Map() + protected readonly _dcConnections: Map = new Map() protected _primaryDc?: DcConnectionManager private _updateHandler: (upd: tl.TypeUpdates, fromClient: boolean) => void @@ -866,7 +866,7 @@ export class NetworkManager { } } - getPoolSize(kind: ConnectionKind, dcId?: number) { + getPoolSize(kind: ConnectionKind, dcId?: number): number { const dc = dcId ? this._dcConnections.get(dcId) : this._primaryDc if (!dc) { @@ -882,7 +882,7 @@ export class NetworkManager { return dc[kind].getPoolSize() } - getPrimaryDcId() { + getPrimaryDcId(): number { if (!this._primaryDc) throw new MtcuteError('Not connected to any DC') return this._primaryDc.dcId diff --git a/packages/core/src/network/server-salt.ts b/packages/core/src/network/server-salt.ts index 64ff42e7..3db7a41d 100644 --- a/packages/core/src/network/server-salt.ts +++ b/packages/core/src/network/server-salt.ts @@ -4,7 +4,7 @@ import type { mtp } from '@mtcute/tl' export class ServerSaltManager { private _futureSalts: mtp.RawMt_future_salt[] = [] - currentSalt = Long.ZERO + currentSalt: Long = Long.ZERO isFetching = false diff --git a/packages/core/src/network/session-connection.ts b/packages/core/src/network/session-connection.ts index da055be9..25074e5e 100644 --- a/packages/core/src/network/session-connection.ts +++ b/packages/core/src/network/session-connection.ts @@ -259,7 +259,7 @@ export class SessionConnection extends PersistentConnection { this.emit('error', error) } - protected onConnectionUsable() { + protected onConnectionUsable(): void { super.onConnectionUsable() if (this.params.withUpdates) { @@ -1499,7 +1499,7 @@ export class SessionConnection extends PersistentConnection { } } - protected _onInactivityTimeout() { + protected _onInactivityTimeout(): void { // we should send all pending acks and other service messages // before dropping the connection // additionally, if we are still waiting for some rpc results, diff --git a/packages/core/src/network/transports/intermediate.ts b/packages/core/src/network/transports/intermediate.ts index 8a8f7a88..9c75af2c 100644 --- a/packages/core/src/network/transports/intermediate.ts +++ b/packages/core/src/network/transports/intermediate.ts @@ -62,7 +62,7 @@ export class PaddedIntermediatePacketCodec extends IntermediatePacketCodec { } private _crypto!: ICryptoProvider - setup?(crypto: ICryptoProvider) { + setup?(crypto: ICryptoProvider): void { this._crypto = crypto } diff --git a/packages/core/src/network/transports/streamed.ts b/packages/core/src/network/transports/streamed.ts index 4a1d24ad..833b6ba6 100644 --- a/packages/core/src/network/transports/streamed.ts +++ b/packages/core/src/network/transports/streamed.ts @@ -9,7 +9,7 @@ import { concatBuffers } from '../../utils/index.js' * multiple transport packets. */ export abstract class StreamedCodec extends EventEmitter { - protected _stream = new Uint8Array(0) + protected _stream: Uint8Array = new Uint8Array(0) /** * Should return whether a full packet is available diff --git a/packages/core/src/storage/memory/driver.ts b/packages/core/src/storage/memory/driver.ts index a2ab1485..c92d86f1 100644 --- a/packages/core/src/storage/memory/driver.ts +++ b/packages/core/src/storage/memory/driver.ts @@ -11,5 +11,5 @@ export class MemoryStorageDriver implements IStorageDriver { return this.states.get(repo) as T } - load() {} + load(): void {} } diff --git a/packages/core/src/storage/memory/index.ts b/packages/core/src/storage/memory/index.ts index 3be5e378..dba91ede 100644 --- a/packages/core/src/storage/memory/index.ts +++ b/packages/core/src/storage/memory/index.ts @@ -17,9 +17,9 @@ export { MemoryStorageDriver } from './driver.js' * or if you know exactly what you're doing. */ export class MemoryStorage implements IMtStorageProvider, ITelegramStorageProvider { - readonly driver = new MemoryStorageDriver() - readonly kv = new MemoryKeyValueRepository(this.driver) - readonly authKeys = new MemoryAuthKeysRepository(this.driver) - readonly peers = new MemoryPeersRepository(this.driver) - readonly refMessages = new MemoryRefMessagesRepository(this.driver) + readonly driver: MemoryStorageDriver = new MemoryStorageDriver() + readonly kv: MemoryKeyValueRepository = new MemoryKeyValueRepository(this.driver) + readonly authKeys: MemoryAuthKeysRepository = new MemoryAuthKeysRepository(this.driver) + readonly peers: MemoryPeersRepository = new MemoryPeersRepository(this.driver) + readonly refMessages: MemoryRefMessagesRepository = new MemoryRefMessagesRepository(this.driver) } diff --git a/packages/core/src/storage/memory/repository/auth-keys.ts b/packages/core/src/storage/memory/repository/auth-keys.ts index 50b4f8d5..9580b430 100644 --- a/packages/core/src/storage/memory/repository/auth-keys.ts +++ b/packages/core/src/storage/memory/repository/auth-keys.ts @@ -8,9 +8,9 @@ interface AuthKeysState { } export class MemoryAuthKeysRepository implements IAuthKeysRepository { - readonly state + readonly state: AuthKeysState constructor(readonly _driver: MemoryStorageDriver) { - this.state = this._driver.getState('authKeys', () => ({ + this.state = this._driver.getState('authKeys', () => ({ authKeys: new Map(), authKeysTemp: new Map(), authKeysTempExpiry: new Map(), diff --git a/packages/core/src/storage/memory/repository/kv.ts b/packages/core/src/storage/memory/repository/kv.ts index 17e5a07f..d4912511 100644 --- a/packages/core/src/storage/memory/repository/kv.ts +++ b/packages/core/src/storage/memory/repository/kv.ts @@ -2,7 +2,7 @@ import type { IKeyValueRepository } from '../../repository/key-value.js' import type { MemoryStorageDriver } from '../driver.js' export class MemoryKeyValueRepository implements IKeyValueRepository { - readonly state + readonly state: Map constructor(readonly _driver: MemoryStorageDriver) { this.state = this._driver.getState>('kv', () => new Map()) } diff --git a/packages/core/src/storage/memory/repository/peers.ts b/packages/core/src/storage/memory/repository/peers.ts index 9e3e889d..e5b5c37f 100644 --- a/packages/core/src/storage/memory/repository/peers.ts +++ b/packages/core/src/storage/memory/repository/peers.ts @@ -8,9 +8,9 @@ interface PeersState { } export class MemoryPeersRepository implements IPeersRepository { - readonly state + readonly state: PeersState constructor(readonly _driver: MemoryStorageDriver) { - this.state = this._driver.getState('peers', () => ({ + this.state = this._driver.getState('peers', () => ({ entities: new Map(), usernameIndex: new Map(), phoneIndex: new Map(), diff --git a/packages/core/src/storage/memory/repository/ref-messages.ts b/packages/core/src/storage/memory/repository/ref-messages.ts index b5609aa1..13a98b57 100644 --- a/packages/core/src/storage/memory/repository/ref-messages.ts +++ b/packages/core/src/storage/memory/repository/ref-messages.ts @@ -6,9 +6,9 @@ interface RefMessagesState { } export class MemoryRefMessagesRepository implements IReferenceMessagesRepository { - readonly state + readonly state: RefMessagesState constructor(readonly _driver: MemoryStorageDriver) { - this.state = this._driver.getState('refMessages', () => ({ + this.state = this._driver.getState('refMessages', () => ({ refs: new Map(), })) } diff --git a/packages/core/src/storage/sqlite/index.ts b/packages/core/src/storage/sqlite/index.ts index 29979dfd..fc9de33c 100644 --- a/packages/core/src/storage/sqlite/index.ts +++ b/packages/core/src/storage/sqlite/index.ts @@ -11,10 +11,10 @@ export { BaseSqliteStorageDriver } export * from './types.js' export class BaseSqliteStorage implements IMtStorageProvider, ITelegramStorageProvider { - readonly authKeys - readonly kv - readonly refMessages - readonly peers + readonly authKeys: SqliteAuthKeysRepository + readonly kv: SqliteKeyValueRepository + readonly refMessages: SqliteRefMessagesRepository + readonly peers: SqlitePeersRepository constructor(readonly driver: BaseSqliteStorageDriver) { this.authKeys = new SqliteAuthKeysRepository(this.driver) diff --git a/packages/core/src/storage/storage.ts b/packages/core/src/storage/storage.ts index 213d2de0..11b3dde9 100644 --- a/packages/core/src/storage/storage.ts +++ b/packages/core/src/storage/storage.ts @@ -9,6 +9,7 @@ import { AuthKeysService } from './service/auth-keys.js' import type { ServiceOptions } from './service/base.js' import { DefaultDcsService } from './service/default-dcs.js' import { FutureSaltsService } from './service/future-salts.js' +import type { IStorageDriver } from './driver.js' interface StorageManagerOptions { provider: IMtStorageProvider @@ -41,12 +42,12 @@ export interface StorageManagerExtraOptions { } export class StorageManager { - readonly provider - readonly driver - readonly log - readonly dcs - readonly salts - readonly keys + readonly provider: IMtStorageProvider + readonly driver: IStorageDriver + readonly log: Logger + readonly dcs: DefaultDcsService + readonly salts: FutureSaltsService + readonly keys: AuthKeysService constructor(readonly options: StorageManagerOptions & StorageManagerExtraOptions) { this.provider = this.options.provider @@ -87,7 +88,7 @@ export class StorageManager { await this.driver.save?.() } - async clear(withAuthKeys = false) { + async clear(withAuthKeys = false): Promise { if (withAuthKeys) { await this.provider.authKeys.deleteAll() } diff --git a/packages/core/src/utils/bigint-utils.ts b/packages/core/src/utils/bigint-utils.ts index 15c5237a..950739a2 100644 --- a/packages/core/src/utils/bigint-utils.ts +++ b/packages/core/src/utils/bigint-utils.ts @@ -4,7 +4,7 @@ import type { ICryptoProvider } from './crypto/abstract.js' /** * Get the minimum number of bits required to represent a number */ -export function bigIntBitLength(n: bigint) { +export function bigIntBitLength(n: bigint): number { // not the fastest way, but at least not .toString(2) and not too complex // taken from: https://stackoverflow.com/a/76616288/22656950 diff --git a/packages/core/src/utils/buffer-utils.ts b/packages/core/src/utils/buffer-utils.ts index 47cd8a4f..f143b786 100644 --- a/packages/core/src/utils/buffer-utils.ts +++ b/packages/core/src/utils/buffer-utils.ts @@ -21,7 +21,7 @@ export function buffersEqual(a: Uint8Array, b: Uint8Array): boolean { * @param start Start offset * @param end End offset */ -export function cloneBuffer(buf: Uint8Array, start = 0, end = buf.length): Uint8Array { +export function cloneBuffer(buf: Uint8Array, start = 0, end: number = buf.length): Uint8Array { const ret = new Uint8Array(end - start) ret.set(buf.subarray(start, end)) @@ -67,7 +67,7 @@ export function dataViewFromBuffer(buf: Uint8Array): DataView { /** * Reverse a buffer (or a part of it) into a new buffer */ -export function bufferToReversed(buf: Uint8Array, start = 0, end = buf.length): Uint8Array { +export function bufferToReversed(buf: Uint8Array, start = 0, end: number = buf.length): Uint8Array { const len = end - start const ret = new Uint8Array(len) diff --git a/packages/core/src/utils/crypto/abstract.ts b/packages/core/src/utils/crypto/abstract.ts index c35d7da7..bcf8223e 100644 --- a/packages/core/src/utils/crypto/abstract.ts +++ b/packages/core/src/utils/crypto/abstract.ts @@ -45,11 +45,11 @@ export interface ICryptoProvider { export abstract class BaseCryptoProvider { abstract randomFill(buf: Uint8Array): void - factorizePQ(pq: Uint8Array) { + factorizePQ(pq: Uint8Array): [Uint8Array, Uint8Array] { return factorizePQSync(this as unknown as ICryptoProvider, pq) } - randomBytes(size: number) { + randomBytes(size: number): Uint8Array { const buf = new Uint8Array(size) this.randomFill(buf) diff --git a/packages/core/src/utils/deque.ts b/packages/core/src/utils/deque.ts index 10c8205f..c8016936 100644 --- a/packages/core/src/utils/deque.ts +++ b/packages/core/src/utils/deque.ts @@ -24,8 +24,8 @@ export class Deque { protected _capacity: number constructor( - readonly maxLength = Infinity, - minCapacity = maxLength === Infinity ? MIN_INITIAL_CAPACITY : maxLength, + readonly maxLength: number = Infinity, + minCapacity: number = maxLength === Infinity ? MIN_INITIAL_CAPACITY : maxLength, ) { let capacity = minCapacity @@ -51,7 +51,7 @@ export class Deque { this._capacity = capacity } - protected _resize() { + protected _resize(): void { const p = this._head const n = this._capacity const r = n - p // number of elements to the right of the head diff --git a/packages/core/src/utils/function-utils.ts b/packages/core/src/utils/function-utils.ts index caa2f981..9126bb22 100644 --- a/packages/core/src/utils/function-utils.ts +++ b/packages/core/src/utils/function-utils.ts @@ -39,7 +39,12 @@ export function throttle(func: () => void, delay: number): ThrottledFunction { return res } -export function asyncResettable Promise>(func: T) { +export function asyncResettable Promise>(func: T): { + run: T + finished: () => boolean + wait: () => Promise | null + reset: () => void +} { let runningPromise: Promise | null = null let finished = false diff --git a/packages/core/src/utils/links/bots.ts b/packages/core/src/utils/links/bots.ts index 2ab4e1cf..aa339f86 100644 --- a/packages/core/src/utils/links/bots.ts +++ b/packages/core/src/utils/links/bots.ts @@ -3,6 +3,7 @@ import type { tl } from '@mtcute/tl' import { isPresent } from '../type-assertions.js' import { assertNever } from '../../types/utils.js' +import type { Deeplink } from './common.js' import { deeplinkBuilder } from './common.js' /** @@ -10,12 +11,12 @@ import { deeplinkBuilder } from './common.js' * * Used to link to bots with a start parameter */ -export const botStart = deeplinkBuilder<{ +export const botStart: Deeplink<{ /** Bot username */ username: string /** Start parameter */ parameter: string -}>({ +}> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: ({ username, parameter }) => ['resolve', { domain: username, start: parameter }], internalParse: (path, query) => { if (path !== 'resolve') return null @@ -137,14 +138,14 @@ function parseBotAdmin(rights: string | null): BotAdminRight[] | undefined { * Note that the user is still free to choose which rights to grant, and * whether to grant them at all. */ -export const botAddToGroup = deeplinkBuilder<{ +export const botAddToGroup: Deeplink<{ /** Bot username */ bot: string /** If specified, the client will call `/start parameter` on the bot once the bot has been added */ parameter?: string /** Admin rights to request */ admin?: BotAdminRight[] -}>({ +}> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: ({ bot, parameter, admin }) => [ 'resolve', { domain: bot, startgroup: parameter ?? true, admin: normalizeBotAdmin(admin) }, @@ -193,12 +194,12 @@ export const botAddToGroup = deeplinkBuilder<{ * Note that the user is still free to choose which rights to grant, and * whether to grant them at all. */ -export const botAddToChannel = deeplinkBuilder<{ +export const botAddToChannel: Deeplink<{ /** Bot username */ bot: string /** Admin rights to request */ admin?: BotAdminRight[] -}>({ +}> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: ({ bot, admin }) => [ 'resolve', { domain: bot, startchannel: true, admin: normalizeBotAdmin(admin) }, @@ -240,12 +241,12 @@ export const botAddToChannel = deeplinkBuilder<{ * * Used to share games. */ -export const botGame = deeplinkBuilder<{ +export const botGame: Deeplink<{ /** Bot username */ bot: string /** Game short name */ game: string -}>({ +}> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: ({ bot, game }) => ['resolve', { domain: bot, game }], internalParse: (path, query) => { if (path !== 'resolve') return null @@ -280,14 +281,14 @@ export const botGame = deeplinkBuilder<{ * and a single bot can offer multiple named web apps, distinguished by * their `short_name`. */ -export const botWebApp = deeplinkBuilder<{ +export const botWebApp: Deeplink<{ /** Bot username */ bot: string /** App short name */ app: string /** Parameter to be passed by the client to messages.requestAppWebView as `start_param` */ parameter?: string -}>({ +}> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: ({ bot, app, parameter }) => ['resolve', { domain: bot, appname: app, startapp: parameter }], internalParse: (path, query) => { if (path !== 'resolve') return null diff --git a/packages/core/src/utils/links/calls.ts b/packages/core/src/utils/links/calls.ts index 05bb6b3f..a69b85de 100644 --- a/packages/core/src/utils/links/calls.ts +++ b/packages/core/src/utils/links/calls.ts @@ -1,3 +1,4 @@ +import type { Deeplink } from './common.js' import { deeplinkBuilder } from './common.js' /** @@ -6,7 +7,7 @@ import { deeplinkBuilder } from './common.js' * Used to join video/voice chats in groups, and livestreams in channels. * Such links are generated using phone.exportGroupCallInvite. */ -export const videoChat = deeplinkBuilder<{ +export const videoChat: Deeplink<{ username: string /** * Invite hash exported if the `can_self_unmute` flag is set when calling `phone.exportGroupCallInvite`: @@ -15,7 +16,7 @@ export const videoChat = deeplinkBuilder<{ */ inviteHash?: string isLivestream?: boolean -}>({ +}> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: ({ username, inviteHash, isLivestream }) => [ 'resolve', { diff --git a/packages/core/src/utils/links/chat.ts b/packages/core/src/utils/links/chat.ts index dcfc4b6f..6cddde1d 100644 --- a/packages/core/src/utils/links/chat.ts +++ b/packages/core/src/utils/links/chat.ts @@ -1,3 +1,4 @@ +import type { Deeplink } from './common.js' import { deeplinkBuilder } from './common.js' /** @@ -5,7 +6,7 @@ import { deeplinkBuilder } from './common.js' * * Used to invite users to private groups and channels */ -export const chatInvite = deeplinkBuilder<{ hash: string }>({ +export const chatInvite: Deeplink<{ hash: string }> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: ({ hash }) => ['join', { invite: hash }], internalParse: (path, query) => { if (path !== 'join') return null @@ -32,7 +33,7 @@ export const chatInvite = deeplinkBuilder<{ hash: string }>({ /** * Chat folder links */ -export const chatFolder = deeplinkBuilder<{ slug: string }>({ +export const chatFolder: Deeplink<{ slug: string }> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: ({ slug }) => ['addlist', { slug }], internalParse: (path, query) => { if (path !== 'addlist') return null @@ -76,127 +77,126 @@ function parseMediaTimestamp(timestamp: string) { * * Note: `channelId` is a non-marked channel ID */ -export const message = deeplinkBuilder< - ({ username: string } | { channelId: number }) & { - /** Message ID */ - id: number - /** Thread ID */ - threadId?: number +export const message: Deeplink<({ username: string } | { channelId: number }) & { + /** Message ID */ + id: number + /** Thread ID */ + threadId?: number - /** - * For comments, `id` will contain the message ID of the channel message that started - * the comment section and this field will contain the message ID of the comment in - * the discussion group. - */ - commentId?: number + /** + * For comments, `id` will contain the message ID of the channel message that started + * the comment section and this field will contain the message ID of the comment in + * the discussion group. + */ + commentId?: number - /** - * Timestamp at which to start playing the media file present - * in the body or in the webpage preview of the message - */ - mediaTimestamp?: number + /** + * Timestamp at which to start playing the media file present + * in the body or in the webpage preview of the message + */ + mediaTimestamp?: number - /** - * Whether this is a link to a specific message in the album or to the entire album - */ - single?: boolean - } ->({ - internalBuild: (params) => { - const common = { - post: params.id, - thread: params.threadId, - comment: params.commentId, - t: params.mediaTimestamp, - single: params.single ? '' : undefined, - } + /** + * Whether this is a link to a specific message in the album or to the entire album + */ + single?: boolean +} +> = /* #__PURE__ */ deeplinkBuilder({ + internalBuild: (params) => { + const common = { + post: params.id, + thread: params.threadId, + comment: params.commentId, + t: params.mediaTimestamp, + single: params.single ? '' : undefined, + } - if ('username' in params) { - return ['resolve', { domain: params.username, ...common }] - } + if ('username' in params) { + return ['resolve', { domain: params.username, ...common }] + } - return ['privatepost', { channel: params.channelId, ...common }] - }, - internalParse: (path, query) => { - const common = { - id: Number(query.get('post')), - threadId: query.has('thread') ? Number(query.get('thread')) : undefined, - commentId: query.has('comment') ? Number(query.get('comment')) : undefined, - mediaTimestamp: query.has('t') ? parseMediaTimestamp(query.get('t')!) : undefined, - single: query.has('single'), - } + return ['privatepost', { channel: params.channelId, ...common }] + }, + internalParse: (path, query) => { + const common = { + id: Number(query.get('post')), + threadId: query.has('thread') ? Number(query.get('thread')) : undefined, + commentId: query.has('comment') ? Number(query.get('comment')) : undefined, + mediaTimestamp: query.has('t') ? parseMediaTimestamp(query.get('t')!) : undefined, + single: query.has('single'), + } - if (path === 'resolve') { - const username = query.get('domain') - if (!username) return null + if (path === 'resolve') { + const username = query.get('domain') + if (!username) return null - return { username, ...common } - } + return { username, ...common } + } - if (path === 'privatepost') { - const channelId = Number(query.get('channel')) - if (!channelId) return null + if (path === 'privatepost') { + const channelId = Number(query.get('channel')) + if (!channelId) return null - return { channelId, ...common } - } + return { channelId, ...common } + } - return null - }, + return null + }, - externalBuild: (params) => { - const common = { - comment: params.commentId, - t: params.mediaTimestamp, - single: params.single ? '' : undefined, - } + externalBuild: (params) => { + const common = { + comment: params.commentId, + t: params.mediaTimestamp, + single: params.single ? '' : undefined, + } - if ('username' in params) { - if (params.threadId) { - return [`${params.username}/${params.threadId}/${params.id}`, common] - } + if ('username' in params) { + if (params.threadId) { + return [`${params.username}/${params.threadId}/${params.id}`, common] + } - return [`${params.username}/${params.id}`, common] - } + return [`${params.username}/${params.id}`, common] + } - if (params.threadId) { - return [`c/${params.channelId}/${params.threadId}/${params.id}`, common] - } + if (params.threadId) { + return [`c/${params.channelId}/${params.threadId}/${params.id}`, common] + } - return [`c/${params.channelId}/${params.id}`, common] - }, - externalParse: (path, query) => { - const chunks = path.split('/') + return [`c/${params.channelId}/${params.id}`, common] + }, + externalParse: (path, query) => { + const chunks = path.split('/') - if (chunks.length < 2) return null + if (chunks.length < 2) return null - const id = Number(chunks[chunks.length - 1]) - if (Number.isNaN(id)) return null + const id = Number(chunks[chunks.length - 1]) + if (Number.isNaN(id)) return null - const common = { - id, - commentId: query.has('comment') ? Number(query.get('comment')) : undefined, - mediaTimestamp: query.has('t') ? parseMediaTimestamp(query.get('t')!) : undefined, - single: query.has('single'), - } + const common = { + id, + commentId: query.has('comment') ? Number(query.get('comment')) : undefined, + mediaTimestamp: query.has('t') ? parseMediaTimestamp(query.get('t')!) : undefined, + single: query.has('single'), + } - if (chunks[0] === 'c') { - const channelId = Number(chunks[1]) - if (Number.isNaN(channelId)) return null + if (chunks[0] === 'c') { + const channelId = Number(chunks[1]) + if (Number.isNaN(channelId)) return null - return { - channelId, - threadId: chunks[3] ? Number(chunks[2]) : undefined, - ...common, - } - } + return { + channelId, + threadId: chunks[3] ? Number(chunks[2]) : undefined, + ...common, + } + } - const username = chunks[0] - if (username[0] === '+') return null + const username = chunks[0] + if (username[0] === '+') return null - return { - username, - threadId: chunks[2] ? Number(chunks[1]) : undefined, - ...common, - } - }, - }) + return { + username, + threadId: chunks[2] ? Number(chunks[1]) : undefined, + ...common, + } + }, +}) diff --git a/packages/core/src/utils/links/misc.ts b/packages/core/src/utils/links/misc.ts index 82d263ba..1932c35a 100644 --- a/packages/core/src/utils/links/misc.ts +++ b/packages/core/src/utils/links/misc.ts @@ -1,3 +1,4 @@ +import type { Deeplink } from './common.js' import { deeplinkBuilder } from './common.js' /** @@ -5,7 +6,7 @@ import { deeplinkBuilder } from './common.js' * * Used to share a prepared message and URL into a chosen chat's text field. */ -export const share = deeplinkBuilder<{ url: string, text?: string }>({ +export const share: Deeplink<{ url: string, text?: string }> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: ({ url, text }) => ['msg_url', { url, text }], internalParse: (path, query) => { if (path !== 'msg_url') return null @@ -35,7 +36,7 @@ export const share = deeplinkBuilder<{ url: string, text?: string }>({ * * Used by users to boost channels, granting them the ability to post stories. */ -export const boost = deeplinkBuilder<{ username: string } | { channelId: number }>({ +export const boost: Deeplink<{ username: string } | { channelId: number }> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: (params) => { if ('username' in params) { return ['boost', { domain: params.username }] @@ -86,7 +87,7 @@ export const boost = deeplinkBuilder<{ username: string } | { channelId: number /** * Link to a shared folder (chat list) */ -export const folder = deeplinkBuilder<{ slug: string }>({ +export const folder: Deeplink<{ slug: string }> = /* #__PURE__ */ deeplinkBuilder({ // tg://addlist?slug=XXX internalBuild: ({ slug }) => ['addlist', { slug }], internalParse: (path, query) => { diff --git a/packages/core/src/utils/links/proxy.ts b/packages/core/src/utils/links/proxy.ts index a9aacc97..c0cc42de 100644 --- a/packages/core/src/utils/links/proxy.ts +++ b/packages/core/src/utils/links/proxy.ts @@ -1,13 +1,14 @@ +import type { Deeplink } from './common.js' import { deeplinkBuilder } from './common.js' /** * MTProxy links */ -export const mtproxy = deeplinkBuilder<{ +export const mtproxy: Deeplink<{ server: string port: number secret: string -}>({ +}> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: params => ['proxy', params], externalBuild: params => ['proxy', params], internalParse: (path, query) => { @@ -37,12 +38,12 @@ export const mtproxy = deeplinkBuilder<{ /** * Socks5 proxy links */ -export const socks5 = deeplinkBuilder<{ +export const socks5: Deeplink<{ server: string port: number user?: string pass?: string -}>({ +}> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: params => ['socks', params], externalBuild: params => ['socks', params], internalParse: (path, query) => { diff --git a/packages/core/src/utils/links/stickers.ts b/packages/core/src/utils/links/stickers.ts index a29edc3a..8d637d8e 100644 --- a/packages/core/src/utils/links/stickers.ts +++ b/packages/core/src/utils/links/stickers.ts @@ -1,3 +1,4 @@ +import type { Deeplink } from './common.js' import { deeplinkBuilder } from './common.js' /** @@ -5,10 +6,10 @@ import { deeplinkBuilder } from './common.js' * * Used to import stickersets or custom emoji stickersets */ -export const stickerset = deeplinkBuilder<{ +export const stickerset: Deeplink<{ slug: string emoji?: boolean -}>({ +}> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: ({ slug, emoji }) => [emoji ? 'addemoji' : 'addstickers', { set: slug }], internalParse: (path, query) => { if (path !== 'addstickers' && path !== 'addemoji') return null diff --git a/packages/core/src/utils/links/user.ts b/packages/core/src/utils/links/user.ts index 39363fa6..5f56a4b1 100644 --- a/packages/core/src/utils/links/user.ts +++ b/packages/core/src/utils/links/user.ts @@ -1,3 +1,4 @@ +import type { Deeplink } from './common.js' import { deeplinkBuilder } from './common.js' /** @@ -5,7 +6,7 @@ import { deeplinkBuilder } from './common.js' * * Used to link to public users, groups and channels */ -export const publicUsername = deeplinkBuilder<{ username: string }>({ +export const publicUsername: Deeplink<{ username: string }> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: ({ username }) => ['resolve', { domain: username }], internalParse: (path, query) => { if (path !== 'resolve') return null @@ -36,7 +37,7 @@ export const publicUsername = deeplinkBuilder<{ username: string }>({ * and they have an expiration date, specified by the expires field of the exportedContactToken * constructor returned by contacts.exportContactToken. */ -export const temporaryProfile = deeplinkBuilder<{ token: string }>({ +export const temporaryProfile: Deeplink<{ token: string }> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: ({ token }) => ['contact', { token }], internalParse: (path, query) => { if (path !== 'contact') return null @@ -60,7 +61,7 @@ export const temporaryProfile = deeplinkBuilder<{ token: string }>({ * * Used to link to public and private users by their phone number. */ -export const phoneNumber = deeplinkBuilder<{ phone: string }>({ +export const phoneNumber: Deeplink<{ phone: string }> = /* #__PURE__ */ deeplinkBuilder({ internalBuild: ({ phone }) => ['resolve', { phone }], internalParse: (path, query) => { if (path !== 'resolve') return null diff --git a/packages/core/src/utils/logger.ts b/packages/core/src/utils/logger.ts index 68858860..93519db5 100644 --- a/packages/core/src/utils/logger.ts +++ b/packages/core/src/utils/logger.ts @@ -1,5 +1,6 @@ import { tl } from '@mtcute/tl' +import type { ICorePlatform } from '../platform.js' import { getPlatform } from '../platform.js' import { isTlRpcError } from './type-assertions.js' @@ -127,11 +128,11 @@ export class Logger { this.mgr.handler(this.color, level, this.tag, this.getPrefix() + fmt, args) } - readonly error = this.log.bind(this, LogManager.ERROR) - readonly warn = this.log.bind(this, LogManager.WARN) - readonly info = this.log.bind(this, LogManager.INFO) - readonly debug = this.log.bind(this, LogManager.DEBUG) - readonly verbose = this.log.bind(this, LogManager.VERBOSE) + readonly error: (fmt: string, ...args: unknown[]) => void = this.log.bind(this, LogManager.ERROR) + readonly warn: (fmt: string, ...args: unknown[]) => void = this.log.bind(this, LogManager.WARN) + readonly info: (fmt: string, ...args: unknown[]) => void = this.log.bind(this, LogManager.INFO) + readonly debug: (fmt: string, ...args: unknown[]) => void = this.log.bind(this, LogManager.DEBUG) + readonly verbose: (fmt: string, ...args: unknown[]) => void = this.log.bind(this, LogManager.VERBOSE) /** * Create a {@link Logger} with the given tag @@ -158,9 +159,9 @@ export class LogManager extends Logger { static DEBUG = 4 static VERBOSE = 5 - readonly platform + readonly platform: ICorePlatform level: number - handler + handler: (color: number, level: number, tag: string, fmt: string, args: unknown[]) => void constructor(tag = 'base') { // workaround because we cant pass this to super diff --git a/packages/core/src/utils/long-utils.ts b/packages/core/src/utils/long-utils.ts index 1e8ac65a..8036a8d7 100644 --- a/packages/core/src/utils/long-utils.ts +++ b/packages/core/src/utils/long-utils.ts @@ -159,23 +159,23 @@ export class LongSet { return this._set.size } - add(val: Long) { + add(val: Long): void { this._set.add(longToFastString(val)) } - delete(val: Long) { + delete(val: Long): void { this._set.delete(longToFastString(val)) } - has(val: Long) { + has(val: Long): boolean { return this._set.has(longToFastString(val)) } - clear() { + clear(): void { this._set.clear() } - toArray() { + toArray(): Long[] { const arr: Long[] = [] for (const v of this._set) { diff --git a/packages/core/src/utils/lru-set.ts b/packages/core/src/utils/lru-set.ts index dc074a64..d80bab0a 100644 --- a/packages/core/src/utils/lru-set.ts +++ b/packages/core/src/utils/lru-set.ts @@ -33,12 +33,12 @@ export class LruSet { this._set = forLong ? new LongSet() : new Set() } - clear() { + clear(): void { this._first = this._last = undefined this._set.clear() } - add(val: T) { + add(val: T): void { if (this._set.has(val as any)) return if (!this._first) this._first = { v: val } @@ -59,7 +59,7 @@ export class LruSet { } } - has(val: T) { + has(val: T): boolean { return this._set.has(val as any) } } diff --git a/packages/create-bot/src/config.ts b/packages/create-bot/src/config.ts index 552b413d..7159afd3 100644 --- a/packages/create-bot/src/config.ts +++ b/packages/create-bot/src/config.ts @@ -8,7 +8,7 @@ export interface UserConfigPersisted { apiHash: string } -export function getConfigFilePath() { +export function getConfigFilePath(): string { switch (process.platform) { case 'linux': return path.join(homedir(), '.local', 'share', 'mtcute-create.json') @@ -35,7 +35,7 @@ export async function readConfig(): Promise { } } -export async function writeConfig(config: UserConfigPersisted) { +export async function writeConfig(config: UserConfigPersisted): Promise { const filePath = getConfigFilePath() await fs.mkdir(path.dirname(filePath), { recursive: true }) diff --git a/packages/create-bot/src/dependencies.ts b/packages/create-bot/src/dependencies.ts index 91cb9eb5..9fdde598 100644 --- a/packages/create-bot/src/dependencies.ts +++ b/packages/create-bot/src/dependencies.ts @@ -11,7 +11,7 @@ export interface DependenciesList { devDepdenencies: string[] } -export function buildDependenciesList(config: UserConfig) { +export function buildDependenciesList(config: UserConfig): DependenciesList { const dependencies = [] const devDepdenencies = [] @@ -57,7 +57,7 @@ export function buildDependenciesList(config: UserConfig) { } } -export async function installDependencies(cwd: string, config: UserConfig) { +export async function installDependencies(cwd: string, config: UserConfig): Promise { const { dependencies, devDepdenencies } = buildDependenciesList(config) if (config.packageManager === PackageManager.Deno) { diff --git a/packages/create-bot/src/package-manager.ts b/packages/create-bot/src/package-manager.ts index d669587a..8a9741e2 100644 --- a/packages/create-bot/src/package-manager.ts +++ b/packages/create-bot/src/package-manager.ts @@ -85,7 +85,7 @@ export function getInstallCommand(params: { mgr: PackageManager, packages: strin return exec } -export function getExecCommand(mgr: PackageManager, ...cmd: string[]) { +export function getExecCommand(mgr: PackageManager, ...cmd: string[]): string[] { switch (mgr) { case PackageManager.Npm: return ['npx', ...cmd] @@ -100,7 +100,7 @@ export function getExecCommand(mgr: PackageManager, ...cmd: string[]) { } } -export function packageManagerToRuntime(mgr: PackageManager) { +export function packageManagerToRuntime(mgr: PackageManager): 'node' | 'bun' | 'deno' { switch (mgr) { case PackageManager.Npm: case PackageManager.Yarn: diff --git a/packages/create-bot/src/utils.ts b/packages/create-bot/src/utils.ts index e2fe3faa..46df61e7 100644 --- a/packages/create-bot/src/utils.ts +++ b/packages/create-bot/src/utils.ts @@ -1,7 +1,7 @@ import * as colors from 'colorette' import { spawn } from 'cross-spawn' -export function exec(cwd: string, ...cmd: string[]) { +export function exec(cwd: string, ...cmd: string[]): Promise { return new Promise((resolve, reject) => { console.log(`${colors.blue('$')} ${cmd.map(it => (it.includes(' ') ? JSON.stringify(it) : it)).join(' ')}`) diff --git a/packages/deno/src/sqlite/driver.ts b/packages/deno/src/sqlite/driver.ts index bc577fa2..64686318 100644 --- a/packages/deno/src/sqlite/driver.ts +++ b/packages/deno/src/sqlite/driver.ts @@ -83,7 +83,7 @@ class WrappedDatabase implements ISqliteDatabase { export class SqliteStorageDriver extends BaseSqliteStorageDriver { constructor( readonly filename = ':memory:', - readonly params?: SqliteStorageDriverOptions, + readonly params?: SqliteStorageDriverOptions | undefined, ) { super() } diff --git a/packages/deno/src/sqlite/index.ts b/packages/deno/src/sqlite/index.ts index 1d5374f0..f4fbb33c 100644 --- a/packages/deno/src/sqlite/index.ts +++ b/packages/deno/src/sqlite/index.ts @@ -8,7 +8,7 @@ export { SqliteStorageDriver } from './driver.js' export class SqliteStorage extends BaseSqliteStorage { constructor( readonly filename = ':memory:', - readonly params?: SqliteStorageDriverOptions, + readonly params?: SqliteStorageDriverOptions | undefined, ) { super(new SqliteStorageDriver(filename, params)) } diff --git a/packages/deno/src/utils/crypto.ts b/packages/deno/src/utils/crypto.ts index 365b74a7..77844bca 100644 --- a/packages/deno/src/utils/crypto.ts +++ b/packages/deno/src/utils/crypto.ts @@ -89,7 +89,7 @@ export class DenoCryptoProvider extends BaseCryptoProvider implements ICryptoPro return toUint8Array(gunzipSync(data)) } - randomFill(buf: Uint8Array) { + randomFill(buf: Uint8Array): void { crypto.getRandomValues(buf) } } diff --git a/packages/deno/src/utils/normalize-file.ts b/packages/deno/src/utils/normalize-file.ts index 6f94c544..c10dc7ce 100644 --- a/packages/deno/src/utils/normalize-file.ts +++ b/packages/deno/src/utils/normalize-file.ts @@ -6,7 +6,11 @@ import { Readable as NodeReadable } from 'node:stream' import type { UploadFileLike } from '@mtcute/core' import { extractFileName } from '@mtcute/core/utils.js' -export async function normalizeFile(file: UploadFileLike) { +export async function normalizeFile(file: UploadFileLike): Promise<{ + file: UploadFileLike + fileName?: string | undefined + fileSize?: number +} | null> { if (typeof file === 'string') { const fd = await Deno.open(file, { read: true }) diff --git a/packages/deno/src/utils/tcp.ts b/packages/deno/src/utils/tcp.ts index afdad6c2..0695aed5 100644 --- a/packages/deno/src/utils/tcp.ts +++ b/packages/deno/src/utils/tcp.ts @@ -134,5 +134,5 @@ export abstract class BaseTcpTransport extends EventEmitter implements ITelegram } export class TcpTransport extends BaseTcpTransport { - _packetCodec = new IntermediatePacketCodec() + _packetCodec: IntermediatePacketCodec = new IntermediatePacketCodec() } diff --git a/packages/dispatcher/src/context/business-message.ts b/packages/dispatcher/src/context/business-message.ts index a290402d..68428f7c 100644 --- a/packages/dispatcher/src/context/business-message.ts +++ b/packages/dispatcher/src/context/business-message.ts @@ -1,4 +1,4 @@ -import type { OmitInputMessageId, ParametersSkip1 } from '@mtcute/core' +import type { Message, OmitInputMessageId, ParametersSkip1, Sticker } from '@mtcute/core' import { BusinessMessage } from '@mtcute/core' import type { TelegramClient } from '@mtcute/core/client.js' import type { @@ -45,12 +45,12 @@ export class BusinessMessageContext extends BusinessMessage implements UpdateCon } /** Get all custom emojis contained in this message (message group), if any */ - getCustomEmojis() { + getCustomEmojis(): Promise { return this.client.getCustomEmojisFromMessages(this.messages) } /** Send a text message to the same chat (and topic, if applicable) as a given message */ - answerText(...params: ParametersSkip1) { + answerText(...params: ParametersSkip1): Promise { const [send, params_ = {}] = params params_.businessConnectionId = this.update.connectionId @@ -58,7 +58,7 @@ export class BusinessMessageContext extends BusinessMessage implements UpdateCon } /** Send a media to the same chat (and topic, if applicable) as a given message */ - answerMedia(...params: ParametersSkip1) { + answerMedia(...params: ParametersSkip1): Promise { const [send, params_ = {}] = params params_.businessConnectionId = this.update.connectionId @@ -66,7 +66,7 @@ export class BusinessMessageContext extends BusinessMessage implements UpdateCon } /** Send a media group to the same chat (and topic, if applicable) as a given message */ - answerMediaGroup(...params: ParametersSkip1) { + answerMediaGroup(...params: ParametersSkip1): Promise { const [send, params_ = {}] = params params_.businessConnectionId = this.update.connectionId @@ -74,7 +74,7 @@ export class BusinessMessageContext extends BusinessMessage implements UpdateCon } /** Send a text message in reply to this message */ - replyText(...params: ParametersSkip1) { + replyText(...params: ParametersSkip1): Promise { const [send, params_ = {}] = params params_.businessConnectionId = this.update.connectionId @@ -82,7 +82,7 @@ export class BusinessMessageContext extends BusinessMessage implements UpdateCon } /** Send a media in reply to this message */ - replyMedia(...params: ParametersSkip1) { + replyMedia(...params: ParametersSkip1): Promise { const [send, params_ = {}] = params params_.businessConnectionId = this.update.connectionId @@ -90,7 +90,7 @@ export class BusinessMessageContext extends BusinessMessage implements UpdateCon } /** Send a media group in reply to this message */ - replyMediaGroup(...params: ParametersSkip1) { + replyMediaGroup(...params: ParametersSkip1): Promise { const [send, params_ = {}] = params params_.businessConnectionId = this.update.connectionId @@ -98,28 +98,28 @@ export class BusinessMessageContext extends BusinessMessage implements UpdateCon } /** Send a text message in reply to this message */ - quoteWithText(params: Parameters[1]) { + quoteWithText(params: Parameters[1]): Promise { params.businessConnectionId = this.update.connectionId return this.client.quoteWithText(this, params) } /** Send a media in reply to this message */ - quoteWithMedia(params: Parameters[1]) { + quoteWithMedia(params: Parameters[1]): Promise { params.businessConnectionId = this.update.connectionId return this.client.quoteWithMedia(this, params) } /** Send a media group in reply to this message */ - quoteWithMediaGroup(params: Parameters[1]) { + quoteWithMediaGroup(params: Parameters[1]): Promise { params.businessConnectionId = this.update.connectionId return this.client.quoteWithMediaGroup(this, params) } /** Delete this message (message group) */ - delete(params?: DeleteMessagesParams) { + delete(params?: DeleteMessagesParams): Promise { return this.client.deleteMessagesById( this.chat.inputPeer, this.messages.map(it => it.id), @@ -128,7 +128,7 @@ export class BusinessMessageContext extends BusinessMessage implements UpdateCon } /** Pin this message */ - pin(params?: OmitInputMessageId[0]>) { + pin(params?: OmitInputMessageId[0]>): Promise { return this.client.pinMessage({ chatId: this.chat.inputPeer, message: this.id, @@ -137,7 +137,7 @@ export class BusinessMessageContext extends BusinessMessage implements UpdateCon } /** Unpin this message */ - unpin() { + unpin(): Promise { return this.client.unpinMessage({ chatId: this.chat.inputPeer, message: this.id, @@ -145,7 +145,7 @@ export class BusinessMessageContext extends BusinessMessage implements UpdateCon } /** Edit this message */ - edit(params: OmitInputMessageId[0]>) { + edit(params: OmitInputMessageId[0]>): Promise { return this.client.editMessage({ chatId: this.chat.inputPeer, message: this.id, @@ -154,7 +154,7 @@ export class BusinessMessageContext extends BusinessMessage implements UpdateCon } /** Forward this message (message group) */ - forwardTo(params: ForwardMessageOptions) { + forwardTo(params: ForwardMessageOptions): Promise { return this.client.forwardMessagesById({ fromChatId: this.chat.inputPeer, messages: this.messages.map(it => it.id), @@ -163,7 +163,7 @@ export class BusinessMessageContext extends BusinessMessage implements UpdateCon } /** Send a copy of this message (message group) */ - copy(params: SendCopyParams & SendCopyGroupParams) { + copy(params: SendCopyParams & SendCopyGroupParams): Promise { if (this.isMessageGroup) { return this.client.sendCopyGroup({ messages: this.messages, @@ -178,7 +178,7 @@ export class BusinessMessageContext extends BusinessMessage implements UpdateCon } /** React to this message */ - react(params: OmitInputMessageId[0]>) { + react(params: OmitInputMessageId[0]>): Promise { return this.client.sendReaction({ chatId: this.chat.inputPeer, message: this.id, diff --git a/packages/dispatcher/src/context/callback-query.ts b/packages/dispatcher/src/context/callback-query.ts index 9e2aa5e6..b92edd0e 100644 --- a/packages/dispatcher/src/context/callback-query.ts +++ b/packages/dispatcher/src/context/callback-query.ts @@ -20,7 +20,7 @@ export class CallbackQueryContext extends CallbackQuery implements UpdateContext } /** Answer to this callback query */ - answer(params: Parameters[1]) { + answer(params: Parameters[1]): Promise { return this.client.answerCallbackQuery(this.id, params) } @@ -37,7 +37,7 @@ export class CallbackQueryContext extends CallbackQuery implements UpdateContext /** * Edit the message that contained the callback button that was clicked. */ - async editMessage(params: Omit[0], 'messageId'>) { + async editMessage(params: Omit[0], 'messageId'>): Promise { return this.client.editMessage({ chatId: this.raw.peer, message: this.raw.msgId, @@ -48,7 +48,9 @@ export class CallbackQueryContext extends CallbackQuery implements UpdateContext /** * Shortcut for getting the message and editing it. */ - async editMessageWith(handler: (msg: Message) => MaybePromise[0]>) { + async editMessageWith( + handler: (msg: Message) => MaybePromise[0]>, + ): Promise { const msg = await this.getMessage() if (!msg) return @@ -75,14 +77,14 @@ export class InlineCallbackQueryContext extends InlineCallbackQuery implements U } /** Answer to this callback query */ - answer(params: Parameters[1]) { + answer(params: Parameters[1]): Promise { return this.client.answerCallbackQuery(this.id, params) } /** * Edit the message that contained the callback button that was clicked. */ - async editMessage(params: Omit[0], 'messageId'>) { + async editMessage(params: Omit[0], 'messageId'>): Promise { return this.client.editInlineMessage({ messageId: this.raw.msgId, ...params, @@ -108,14 +110,14 @@ export class BusinessCallbackQueryContext } /** Answer to this callback query */ - answer(params: Parameters[1]) { + answer(params: Parameters[1]): Promise { return this.client.answerCallbackQuery(this.id, params) } /** * Edit the message that contained the callback button that was clicked. */ - async editMessage(params: Omit[0], 'messageId'>) { + async editMessage(params: Omit[0], 'messageId'>): Promise { return this.client.editMessage({ message: this.message, businessConnectionId: this.connectionId, diff --git a/packages/dispatcher/src/context/inline-query.ts b/packages/dispatcher/src/context/inline-query.ts index f8bfd8dc..6d24134a 100644 --- a/packages/dispatcher/src/context/inline-query.ts +++ b/packages/dispatcher/src/context/inline-query.ts @@ -20,7 +20,7 @@ export class InlineQueryContext extends InlineQuery implements UpdateContext) { + answer(...params: ParametersSkip1): Promise { return this.client.answerInlineQuery(this.id, ...params) } } diff --git a/packages/dispatcher/src/context/message.ts b/packages/dispatcher/src/context/message.ts index 213fd91c..f8c06d33 100644 --- a/packages/dispatcher/src/context/message.ts +++ b/packages/dispatcher/src/context/message.ts @@ -1,7 +1,12 @@ -import type { OmitInputMessageId, ParametersSkip1, Peer } from '@mtcute/core' +import type { OmitInputMessageId, ParametersSkip1, Peer, Sticker } from '@mtcute/core' import { Message, MtPeerNotFoundError } from '@mtcute/core' import type { TelegramClient } from '@mtcute/core/client.js' -import type { DeleteMessagesParams, ForwardMessageOptions, SendCopyGroupParams, SendCopyParams } from '@mtcute/core/methods.js' +import type { + DeleteMessagesParams, + ForwardMessageOptions, + SendCopyGroupParams, + SendCopyParams, +} from '@mtcute/core/methods.js' import type { UpdateContext } from './base.js' @@ -63,82 +68,82 @@ export class MessageContext extends Message implements UpdateContext { } /** Get a message that this message is a reply to */ - getReplyTo() { + getReplyTo(): Promise { return this.client.getReplyTo(this) } /** If this is a channel post, get its automatic forward in the discussion group */ - getDiscussionMessage() { + getDiscussionMessage(): Promise { return this.client.getDiscussionMessage({ chatId: this.chat.inputPeer, message: this.id }) } /** Get all custom emojis contained in this message (message group), if any */ - getCustomEmojis() { + getCustomEmojis(): Promise { return this.client.getCustomEmojisFromMessages(this.messages) } /** Send a text message to the same chat (and topic, if applicable) as a given message */ - answerText(...params: ParametersSkip1) { + answerText(...params: ParametersSkip1): Promise { return this.client.answerText(this, ...params) } /** Send a media to the same chat (and topic, if applicable) as a given message */ - answerMedia(...params: ParametersSkip1) { + answerMedia(...params: ParametersSkip1): Promise { return this.client.answerMedia(this, ...params) } /** Send a media group to the same chat (and topic, if applicable) as a given message */ - answerMediaGroup(...params: ParametersSkip1) { + answerMediaGroup(...params: ParametersSkip1): Promise { return this.client.answerMediaGroup(this, ...params) } /** Send a text message in reply to this message */ - replyText(...params: ParametersSkip1) { + replyText(...params: ParametersSkip1): Promise { return this.client.replyText(this, ...params) } /** Send a media in reply to this message */ - replyMedia(...params: ParametersSkip1) { + replyMedia(...params: ParametersSkip1): Promise { return this.client.replyMedia(this, ...params) } /** Send a media group in reply to this message */ - replyMediaGroup(...params: ParametersSkip1) { + replyMediaGroup(...params: ParametersSkip1): Promise { return this.client.replyMediaGroup(this, ...params) } /** Send a text message in reply to this message */ - quoteWithText(params: Parameters[1]) { + quoteWithText(params: Parameters[1]): Promise { return this.client.quoteWithText(this, params) } /** Send a media in reply to this message */ - quoteWithMedia(params: Parameters[1]) { + quoteWithMedia(params: Parameters[1]): Promise { return this.client.quoteWithMedia(this, params) } /** Send a media group in reply to this message */ - quoteWithMediaGroup(params: Parameters[1]) { + quoteWithMediaGroup(params: Parameters[1]): Promise { return this.client.quoteWithMediaGroup(this, params) } /** Send a text as a comment to this message */ - commentText(...params: ParametersSkip1) { + commentText(...params: ParametersSkip1): Promise { return this.client.commentText(this, ...params) } /** Send a media as a comment to this message */ - commentMedia(...params: ParametersSkip1) { + commentMedia(...params: ParametersSkip1): Promise { return this.client.commentMedia(this, ...params) } /** Send a media group as a comment to this message */ - commentMediaGroup(...params: ParametersSkip1) { + commentMediaGroup(...params: ParametersSkip1): Promise { return this.client.commentMediaGroup(this, ...params) } /** Delete this message (message group) */ - delete(params?: DeleteMessagesParams) { + delete(params?: DeleteMessagesParams): Promise { return this.client.deleteMessagesById( this.chat.inputPeer, this.messages.map(it => it.id), @@ -147,7 +152,7 @@ export class MessageContext extends Message implements UpdateContext { } /** Pin this message */ - pin(params?: OmitInputMessageId[0]>) { + pin(params?: OmitInputMessageId[0]>): Promise { return this.client.pinMessage({ chatId: this.chat.inputPeer, message: this.id, @@ -156,7 +161,7 @@ export class MessageContext extends Message implements UpdateContext { } /** Unpin this message */ - unpin() { + unpin(): Promise { return this.client.unpinMessage({ chatId: this.chat.inputPeer, message: this.id, @@ -164,7 +169,7 @@ export class MessageContext extends Message implements UpdateContext { } /** Edit this message */ - edit(params: OmitInputMessageId[0]>) { + edit(params: OmitInputMessageId[0]>): Promise { return this.client.editMessage({ chatId: this.chat.inputPeer, message: this.id, @@ -173,7 +178,7 @@ export class MessageContext extends Message implements UpdateContext { } /** Forward this message (message group) */ - forwardTo(params: ForwardMessageOptions) { + forwardTo(params: ForwardMessageOptions): Promise { return this.client.forwardMessagesById({ fromChatId: this.chat.inputPeer, messages: this.messages.map(it => it.id), @@ -182,7 +187,7 @@ export class MessageContext extends Message implements UpdateContext { } /** Send a copy of this message (message group) */ - copy(params: SendCopyParams & SendCopyGroupParams) { + copy(params: SendCopyParams & SendCopyGroupParams): Promise | Promise { if (this.isMessageGroup) { return this.client.sendCopyGroup({ messages: this.messages, @@ -197,7 +202,9 @@ export class MessageContext extends Message implements UpdateContext { } /** React to this message */ - react(params: OmitInputMessageId[0]>) { + react( + params: OmitInputMessageId[0]>, + ): Promise { return this.client.sendReaction({ chatId: this.chat.inputPeer, message: this.id, diff --git a/packages/dispatcher/src/context/parse.ts b/packages/dispatcher/src/context/parse.ts index 84bd4177..769d2cf4 100644 --- a/packages/dispatcher/src/context/parse.ts +++ b/packages/dispatcher/src/context/parse.ts @@ -1,4 +1,21 @@ -import type { ParsedUpdate } from '@mtcute/core' +import type { + BotReactionCountUpdate, + BotReactionUpdate, + BotStoppedUpdate, + BusinessConnection, + ChatJoinRequestUpdate, + ChatMemberUpdate, + DeleteBusinessMessageUpdate, + DeleteMessageUpdate, + DeleteStoryUpdate, + HistoryReadUpdate, + ParsedUpdate, + PollUpdate, + PollVoteUpdate, + StoryUpdate, + UserStatusUpdate, + UserTypingUpdate, +} from '@mtcute/core' import type { TelegramClient } from '@mtcute/core/client.js' import type { UpdateContextDistributed } from './base.js' @@ -10,8 +27,36 @@ import { InlineQueryContext } from './inline-query.js' import { MessageContext } from './message.js' import { PreCheckoutQueryContext } from './pre-checkout-query.js' +export type UpdateContextType = + | MessageContext + | InlineQueryContext + | ChosenInlineResultContext + | CallbackQueryContext + | InlineCallbackQueryContext + | BusinessCallbackQueryContext + | ChatJoinRequestUpdateContext + | PreCheckoutQueryContext + | BusinessMessageContext + | UpdateContextDistributed< + | DeleteMessageUpdate + | ChatMemberUpdate + | PollUpdate + | PollVoteUpdate + | UserStatusUpdate + | UserTypingUpdate + | HistoryReadUpdate + | BotStoppedUpdate + | ChatJoinRequestUpdate + | StoryUpdate + | DeleteStoryUpdate + | BotReactionUpdate + | BotReactionCountUpdate + | BusinessConnection + | DeleteBusinessMessageUpdate + > + /** @internal */ -export function _parsedUpdateToContext(client: TelegramClient, update: ParsedUpdate) { +export function _parsedUpdateToContext(client: TelegramClient, update: ParsedUpdate): UpdateContextType { switch (update.name) { case 'new_message': case 'edit_message': @@ -43,5 +88,3 @@ export function _parsedUpdateToContext(client: TelegramClient, update: ParsedUpd return _update } - -export type UpdateContextType = ReturnType diff --git a/packages/dispatcher/src/filters/bots.ts b/packages/dispatcher/src/filters/bots.ts index c074f26c..95bfe291 100644 --- a/packages/dispatcher/src/filters/bots.ts +++ b/packages/dispatcher/src/filters/bots.ts @@ -1,11 +1,11 @@ -import type { MaybeArray, MaybePromise, Message } from '@mtcute/core' +import type { Chat, MaybeArray, MaybePromise, Message } from '@mtcute/core' import type { BusinessMessageContext } from '../context/business-message.js' import type { MessageContext } from '../context/message.js' import { chat } from './chat.js' import { and, or } from './logic.js' -import type { UpdateFilter } from './types.js' +import type { Modify, UpdateFilter } from './types.js' /** * Filter messages that call the given command(s).. @@ -97,13 +97,30 @@ export function command(commands: MaybeArray, { * Shorthand filter that matches /start commands sent to bot's * private messages. */ -export const start = and(chat('private'), command('start')) +export const start: UpdateFilter< + MessageContext | BusinessMessageContext, + { + chat: Modify + command: string[] + } +> = and(chat('private'), command('start')) /** * Shorthand filter that matches /start commands * sent in groups (i.e. using `?startgroup` parameter). */ -export const startGroup = and(or(chat('supergroup'), chat('group')), command('start')) +export const startGroup: UpdateFilter< + MessageContext | BusinessMessageContext, + { + chat: Modify + command: string[] + }, + never +> = and(or(chat('supergroup'), chat('group')), command('start')) function deeplinkBase(base: UpdateFilter) { return ( @@ -156,7 +173,10 @@ function deeplinkBase(base: UpdateFilter) => UpdateFilter< + MessageContext | BusinessMessageContext, + { command: string[] } +> = deeplinkBase(start) /** * Filter for group deep links (i.e. `/start `). @@ -164,4 +184,7 @@ export const deeplink = deeplinkBase(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 deeplinkGroup = deeplinkBase(startGroup) +export const deeplinkGroup: (params: MaybeArray) => UpdateFilter< + MessageContext | BusinessMessageContext, + { command: string[] } +> = deeplinkBase(startGroup) diff --git a/packages/dispatcher/src/filters/message.ts b/packages/dispatcher/src/filters/message.ts index 178478dd..4f8e1e27 100644 --- a/packages/dispatcher/src/filters/message.ts +++ b/packages/dispatcher/src/filters/message.ts @@ -1,16 +1,29 @@ import type { + Audio, + Contact, + Dice, + Document, + Game, + Invoice, + LiveLocation, + Location, MaybeArray, Message, MessageAction, MessageMediaType, Peer, + Photo, + Poll, RepliedMessageInfo, RepliedMessageOrigin, Sticker, StickerSourceType, StickerType, User, + Venue, Video, + Voice, + WebPage, _RepliedMessageAssertionsByOrigin, } from '@mtcute/core' import { @@ -68,41 +81,44 @@ export const media: UpdateFilter(type: T): UpdateFilter }> { +export function mediaOf(type: T): UpdateFilter< + Message, + { media: Extract } +> { return msg => msg.media?.type === type } /** Filter messages containing a photo */ -export const photo = mediaOf('photo') +export const photo: UpdateFilter = mediaOf('photo') /** Filter messages containing a dice */ -export const dice = mediaOf('dice') +export const dice: UpdateFilter = mediaOf('dice') /** Filter messages containing a contact */ -export const contact = mediaOf('contact') +export const contact: UpdateFilter = mediaOf('contact') /** Filter messages containing an audio file */ -export const audio = mediaOf('audio') +export const audio: UpdateFilter = mediaOf('audio') /** Filter messages containing a voice message (audio-only) */ -export const voice = mediaOf('voice') +export const voice: UpdateFilter = mediaOf('voice') /** Filter messages containing a sticker */ -export const sticker = mediaOf('sticker') +export const sticker: UpdateFilter = mediaOf('sticker') /** Filter messages containing a document (a file) */ -export const document = mediaOf('document') +export const document: UpdateFilter = mediaOf('document') /** Filter messages containing any video (videos, round messages and animations) */ -export const anyVideo = mediaOf('video') +export const anyVideo: UpdateFilter = mediaOf('video') /** Filter messages containing a static location */ -export const location = mediaOf('location') +export const location: UpdateFilter = mediaOf('location') /** Filter messages containing a live location */ -export const liveLocation = mediaOf('live_location') +export const liveLocation: UpdateFilter = mediaOf('live_location') /** Filter messages containing a game */ -export const game = mediaOf('game') +export const game: UpdateFilter = mediaOf('game') /** Filter messages containing a web page */ -export const webpage = mediaOf('webpage') +export const webpage: UpdateFilter = mediaOf('webpage') /** Filter messages containing a venue */ -export const venue = mediaOf('venue') +export const venue: UpdateFilter = mediaOf('venue') /** Filter messages containing a poll */ -export const poll = mediaOf('poll') +export const poll: UpdateFilter = mediaOf('poll') /** Filter messages containing an invoice */ -export const invoice = mediaOf('invoice') +export const invoice: UpdateFilter = mediaOf('invoice') /** * Filter messages containing any location (live or static). @@ -224,7 +240,10 @@ export function action['type']>(type: May return msg => msg.action?.type === type } -export function sender(type: T): UpdateFilter }> { +export function sender(type: T): UpdateFilter< + Message, + { sender: Extract } +> { return msg => msg.sender.type === type } @@ -235,7 +254,13 @@ export function sender(type: T): UpdateFilt * * Optionally, you can pass a filter that will be applied to the replied message. */ -export function replyTo(filter?: UpdateFilter): UpdateFilter Promise }, State> { +export function replyTo( + filter?: UpdateFilter, +): UpdateFilter< + MessageContext | BusinessMessageContext, + { getReplyTo: () => Promise }, + State + > { return async (msg, state) => { if (!msg.replyToMessage?.id) return false @@ -256,7 +281,9 @@ export function replyTo(filter?: UpdateFilter(filter?: UpdateFilter): UpdateFilter { +export function withCompleteSender( + filter?: UpdateFilter, +): UpdateFilter { return async (msg, state) => { try { await msg.getCompleteSender() diff --git a/packages/dispatcher/src/state/providers/memory.ts b/packages/dispatcher/src/state/providers/memory.ts index c5bfe1d3..78b1f858 100644 --- a/packages/dispatcher/src/state/providers/memory.ts +++ b/packages/dispatcher/src/state/providers/memory.ts @@ -15,8 +15,8 @@ interface RateLimitDto { } class MemoryStateRepository implements IStateRepository { - readonly state - readonly rl + readonly state: Map + readonly rl: Map constructor(readonly _driver: MemoryStorageDriver) { this.state = this._driver.getState>('dispatcher_fsm', () => new Map()) this.rl = this._driver.getState>('rl', () => new Map()) @@ -99,7 +99,7 @@ class MemoryStateRepository implements IStateRepository { } export class MemoryStateStorage implements IStateStorageProvider { - readonly state + readonly state: MemoryStateRepository constructor(readonly driver: MemoryStorageDriver = new MemoryStorageDriver()) { this.state = new MemoryStateRepository(this.driver) diff --git a/packages/dispatcher/src/state/providers/sqlite.ts b/packages/dispatcher/src/state/providers/sqlite.ts index cb672862..3646c98c 100644 --- a/packages/dispatcher/src/state/providers/sqlite.ts +++ b/packages/dispatcher/src/state/providers/sqlite.ts @@ -116,12 +116,12 @@ class SqliteStateRepository implements IStateRepository { } export class SqliteStateStorage implements IStateStorageProvider { - readonly state + readonly state: SqliteStateRepository constructor(readonly driver: BaseSqliteStorageDriver) { this.state = new SqliteStateRepository(driver) } - static from(provider: BaseSqliteStorage) { + static from(provider: BaseSqliteStorage): SqliteStateStorage { return new SqliteStateStorage(provider.driver) } } diff --git a/packages/dispatcher/src/state/service.ts b/packages/dispatcher/src/state/service.ts index d2d6f30c..719b9867 100644 --- a/packages/dispatcher/src/state/service.ts +++ b/packages/dispatcher/src/state/service.ts @@ -1,4 +1,5 @@ import { LruMap, asyncResettable } from '@mtcute/core/utils.js' +import type { MaybePromise } from '@mtcute/core' import type { IStateStorageProvider } from './provider.js' @@ -16,14 +17,14 @@ export class StateService { this._loaded = true }) - async load() { + async load(): Promise { await this._load.run() this._vacuumTimer = setInterval(() => { Promise.resolve(this.provider.state.vacuum(Date.now())).catch(() => {}) }, 300_000) } - async destroy() { + async destroy(): Promise { await this.provider.driver.save?.() await this.provider.driver.destroy?.() clearInterval(this._vacuumTimer) @@ -68,11 +69,11 @@ export class StateService { return this.deleteState(makeCurrentSceneKey(key)) } - getRateLimit(key: string, limit: number, window: number) { + getRateLimit(key: string, limit: number, window: number): MaybePromise<[number, number]> { return this.provider.state.getRateLimit(key, Date.now(), limit, window) } - resetRateLimit(key: string) { + resetRateLimit(key: string): MaybePromise { return this.provider.state.resetRateLimit(key) } } diff --git a/packages/dispatcher/src/wizard.ts b/packages/dispatcher/src/wizard.ts index 43bef7f6..1fb9ef5d 100644 --- a/packages/dispatcher/src/wizard.ts +++ b/packages/dispatcher/src/wizard.ts @@ -3,6 +3,7 @@ import type { MaybePromise } from '@mtcute/core' import type { MessageContext } from './context/message.js' import type { DispatcherParams } from './dispatcher.js' import { Dispatcher } from './dispatcher.js' +import type { UpdateFilter } from './filters/index.js' import { filters } from './filters/index.js' import type { UpdateState } from './state/update-state.js' @@ -61,7 +62,7 @@ export class WizardScene extends Dispatcher, step: number) { + async goToStep(state: UpdateState, step: number): Promise { if (step >= this._steps) { await state.exit() } else { @@ -72,7 +73,7 @@ export class WizardScene extends Dispatcher, count = 1) { + async skip(state: UpdateState, count = 1): Promise { const { $step } = (await state.get()) || {} if ($step === undefined) throw new Error('Wizard state is not initialized') @@ -82,7 +83,8 @@ export class WizardScene extends Dispatcher { const filter = filters.state(it => it.$step === step) if (step === 0) return filters.or(filters.stateEmpty, filter) @@ -93,7 +95,8 @@ export class WizardScene extends Dispatcher { return WizardScene.onNthStep(this._steps) } diff --git a/packages/file-id/src/types-inner.ts b/packages/file-id/src/types-inner.ts index 211af9fa..0270f12c 100644 --- a/packages/file-id/src/types-inner.ts +++ b/packages/file-id/src/types-inner.ts @@ -3,8 +3,8 @@ import type Long from 'long' export const PERSISTENT_ID_VERSION_OLD = 2 export const PERSISTENT_ID_VERSION = 4 -export const WEB_LOCATION_FLAG = 1 << 24 -export const FILE_REFERENCE_FLAG = 1 << 25 +export const WEB_LOCATION_FLAG: number = 1 << 24 +export const FILE_REFERENCE_FLAG: number = 1 << 25 export const CURRENT_VERSION = 48 diff --git a/packages/http-proxy/index.ts b/packages/http-proxy/index.ts index 89659f7c..30bd4755 100644 --- a/packages/http-proxy/index.ts +++ b/packages/http-proxy/index.ts @@ -160,5 +160,5 @@ export abstract class BaseHttpProxyTcpTransport extends BaseTcpTransport { * (unless you want to use a custom codec). */ export class HttpProxyTcpTransport extends BaseHttpProxyTcpTransport { - _packetCodec = new IntermediatePacketCodec() + _packetCodec: IntermediatePacketCodec = new IntermediatePacketCodec() } diff --git a/packages/mtproxy/fake-tls.ts b/packages/mtproxy/fake-tls.ts index a49f3b5c..2c379260 100644 --- a/packages/mtproxy/fake-tls.ts +++ b/packages/mtproxy/fake-tls.ts @@ -277,7 +277,7 @@ export async function generateFakeTlsHeader(domain: string, secret: Buffer, cryp * @internal */ export class FakeTlsPacketCodec extends WrappedCodec implements IPacketCodec { - protected _stream = Buffer.alloc(0) + protected _stream: Buffer = Buffer.alloc(0) private _header!: Buffer private _isFirstTls = true diff --git a/packages/node/src/client.ts b/packages/node/src/client.ts index 217c00a7..354bf248 100644 --- a/packages/node/src/client.ts +++ b/packages/node/src/client.ts @@ -1,5 +1,6 @@ import type { Interface as RlInterface } from 'node:readline' import { createInterface } from 'node:readline' +import type { Readable } from 'node:stream' import type { FileDownloadLocation, FileDownloadParameters, ITelegramStorageProvider, PartialOnly, User } from '@mtcute/core' import type { @@ -157,7 +158,7 @@ export class TelegramClient extends TelegramClientBase { return downloadToFile(this, filename, location, params) } - downloadAsNodeStream(location: FileDownloadLocation, params?: FileDownloadParameters | undefined) { + downloadAsNodeStream(location: FileDownloadLocation, params?: FileDownloadParameters | undefined): Readable { return downloadAsNodeStream(this, location, params) } } diff --git a/packages/node/src/common-internals-node/logging.ts b/packages/node/src/common-internals-node/logging.ts index 7a842f32..7eb7b4fb 100644 --- a/packages/node/src/common-internals-node/logging.ts +++ b/packages/node/src/common-internals-node/logging.ts @@ -21,7 +21,13 @@ const LEVEL_NAMES = isTty const TAG_COLORS = [6, 2, 3, 4, 5, 1].map(i => `\x1B[3${i};1m`) /** @internal */ -export const defaultLoggingHandler = isTty +export const defaultLoggingHandler: ( + color: number, + level: number, + tag: string, + fmt: string, + args: unknown[] +) => void = isTty ? (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) diff --git a/packages/node/src/sqlite/driver.ts b/packages/node/src/sqlite/driver.ts index 4d89650f..29b0490c 100644 --- a/packages/node/src/sqlite/driver.ts +++ b/packages/node/src/sqlite/driver.ts @@ -25,7 +25,7 @@ export interface SqliteStorageDriverOptions { export class SqliteStorageDriver extends BaseSqliteStorageDriver { constructor( readonly filename = ':memory:', - readonly params?: SqliteStorageDriverOptions, + readonly params?: SqliteStorageDriverOptions | undefined, ) { super() } diff --git a/packages/node/src/sqlite/index.ts b/packages/node/src/sqlite/index.ts index 1d5374f0..f4fbb33c 100644 --- a/packages/node/src/sqlite/index.ts +++ b/packages/node/src/sqlite/index.ts @@ -8,7 +8,7 @@ export { SqliteStorageDriver } from './driver.js' export class SqliteStorage extends BaseSqliteStorage { constructor( readonly filename = ':memory:', - readonly params?: SqliteStorageDriverOptions, + readonly params?: SqliteStorageDriverOptions | undefined, ) { super(new SqliteStorageDriver(filename, params)) } diff --git a/packages/node/src/utils/crypto.ts b/packages/node/src/utils/crypto.ts index 4cc3de80..2415c726 100644 --- a/packages/node/src/utils/crypto.ts +++ b/packages/node/src/utils/crypto.ts @@ -63,7 +63,7 @@ export abstract class BaseNodeCryptoProvider extends BaseCryptoProvider { return gunzipSync(data) } - randomFill(buf: Uint8Array) { + randomFill(buf: Uint8Array): void { randomFillSync(buf) } } diff --git a/packages/node/src/utils/normalize-file.ts b/packages/node/src/utils/normalize-file.ts index 01af59bf..3f8eb784 100644 --- a/packages/node/src/utils/normalize-file.ts +++ b/packages/node/src/utils/normalize-file.ts @@ -7,7 +7,11 @@ import type { UploadFileLike } from '@mtcute/core' import { nodeStreamToWeb } from './stream-utils.js' -export async function normalizeFile(file: UploadFileLike) { +export async function normalizeFile(file: UploadFileLike): Promise<{ + file: UploadFileLike + fileName?: string | undefined + fileSize?: number +} | null> { if (typeof file === 'string') { file = createReadStream(file) } diff --git a/packages/node/src/utils/tcp.ts b/packages/node/src/utils/tcp.ts index 1c2bd6ea..8dafe64b 100644 --- a/packages/node/src/utils/tcp.ts +++ b/packages/node/src/utils/tcp.ts @@ -136,5 +136,5 @@ export abstract class BaseTcpTransport extends EventEmitter implements ITelegram } export class TcpTransport extends BaseTcpTransport { - _packetCodec = new IntermediatePacketCodec() + _packetCodec: IntermediatePacketCodec = new IntermediatePacketCodec() } diff --git a/packages/node/src/utils/version.ts b/packages/node/src/utils/version.ts index 0bfcd35b..8f3ee833 100644 --- a/packages/node/src/utils/version.ts +++ b/packages/node/src/utils/version.ts @@ -1,5 +1,7 @@ -export const NODE_VERSION = typeof process !== 'undefined' && 'node' in process.versions ? process.versions.node : null -export const NODE_VERSION_TUPLE = NODE_VERSION ? /* #__PURE__ */ NODE_VERSION.split('.').map(Number) : null +export const NODE_VERSION: string | null + = typeof process !== 'undefined' && 'node' in process.versions ? process.versions.node : null +export const NODE_VERSION_TUPLE: number[] | null + = NODE_VERSION ? /* #__PURE__ */ NODE_VERSION.split('.').map(Number) : null export function isNodeVersionAfter(major: number, minor: number, patch: number): boolean { if (!NODE_VERSION_TUPLE) return true // assume non-node environment is always "after" diff --git a/packages/socks-proxy/index.ts b/packages/socks-proxy/index.ts index 76ecc9d9..67563e15 100644 --- a/packages/socks-proxy/index.ts +++ b/packages/socks-proxy/index.ts @@ -415,5 +415,5 @@ export abstract class BaseSocksTcpTransport extends BaseTcpTransport { * (unless you want to use a custom codec). */ export class SocksTcpTransport extends BaseSocksTcpTransport { - _packetCodec = new IntermediatePacketCodec() + _packetCodec: IntermediatePacketCodec = new IntermediatePacketCodec() } diff --git a/packages/test/src/client.ts b/packages/test/src/client.ts index 17dafa78..08650cf7 100644 --- a/packages/test/src/client.ts +++ b/packages/test/src/client.ts @@ -61,7 +61,7 @@ export class StubTelegramClient extends BaseTelegramClient { * * Useful for testing "offline" methods */ - static offline() { + static offline(): StubTelegramClient { const client = new StubTelegramClient() client.call = (obj) => { @@ -94,8 +94,8 @@ export class StubTelegramClient extends BaseTelegramClient { // some fake peers handling // - readonly _knownChats = new Map() - readonly _knownUsers = new Map() + readonly _knownChats: Map = new Map() + readonly _knownUsers: Map = new Map() _selfId = 0 async registerPeers(...peers: (tl.TypeUser | tl.TypeChat)[]): Promise { @@ -110,7 +110,7 @@ export class StubTelegramClient extends BaseTelegramClient { } } - getPeers(ids: InputPeerId[]) { + getPeers(ids: InputPeerId[]): { users: tl.TypeUser[], chats: tl.TypeChat[] } { const users: tl.TypeUser[] = [] const chats: tl.TypeChat[] = [] @@ -219,7 +219,7 @@ export class StubTelegramClient extends BaseTelegramClient { return state } - getNextMessageId(chatId = 0) { + getNextMessageId(chatId = 0): number { const state = this.getMessageBox(chatId) const nextId = state.lastMessageId + 1 @@ -228,7 +228,7 @@ export class StubTelegramClient extends BaseTelegramClient { return nextId } - getNextPts(chatId = 0, count = 1) { + getNextPts(chatId = 0, count = 1): number { const state = this.getMessageBox(chatId) const nextPts = state.pts + count @@ -237,11 +237,11 @@ export class StubTelegramClient extends BaseTelegramClient { return nextPts } - getNextQts() { + getNextQts(): number { return this._lastQts++ } - getNextDate() { + getNextDate(): number { return (this._lastDate = Math.floor(Date.now() / 1000)) } diff --git a/packages/test/src/crypto.ts b/packages/test/src/crypto.ts index 35e0e282..eff3dd72 100644 --- a/packages/test/src/crypto.ts +++ b/packages/test/src/crypto.ts @@ -28,7 +28,7 @@ da91539fcc7b03d2b8b1381bd6023fff20278344ad944d364ba684842db3901c346335f0d455eda4 fa3de8e50aac96c1275591a1221c32a60a1513370a33a228e00894341b10cf44a6ae6ac250d17a364e956ab1a17b068df3fb2d5b5a672d8a409eeb8b6ca1ade6 `.replace(/\s/g, '') -export function withFakeRandom(provider: ICryptoProvider, source = DEFAULT_ENTROPY): ICryptoProvider { +export function withFakeRandom(provider: ICryptoProvider, source: string = DEFAULT_ENTROPY): ICryptoProvider { const sourceBytes = getPlatform().hexDecode(source) let offset = 0 @@ -51,7 +51,7 @@ export function withFakeRandom(provider: ICryptoProvider, source = DEFAULT_ENTRO }) } -export function useFakeMathRandom(source = DEFAULT_ENTROPY): void { +export function useFakeMathRandom(source: string = DEFAULT_ENTROPY): void { const sourceBytes = getPlatform().hexDecode(source) const dv = dataViewFromBuffer(sourceBytes) @@ -72,7 +72,7 @@ export function useFakeMathRandom(source = DEFAULT_ENTROPY): void { }) } -export async function defaultTestCryptoProvider(source = DEFAULT_ENTROPY): Promise { +export async function defaultTestCryptoProvider(source: string = DEFAULT_ENTROPY): Promise { const prov = withFakeRandom(defaultCryptoProvider, source) await prov.initialize?.() @@ -250,7 +250,7 @@ export function testCryptoProvider(c: ICryptoProvider): void { }) } -export function u8HexDecode(hex: string) { +export function u8HexDecode(hex: string): Uint8Array { const buf = getPlatform().hexDecode(hex) // eslint-disable-next-line no-restricted-globals diff --git a/packages/test/src/platform.ts b/packages/test/src/platform.ts index 7a43f98f..c1176a07 100644 --- a/packages/test/src/platform.ts +++ b/packages/test/src/platform.ts @@ -1,5 +1,5 @@ import { NodePlatform } from '@mtcute/node' import { NodeCryptoProvider } from '@mtcute/node/utils.js' -export const defaultPlatform = new NodePlatform() -export const defaultCryptoProvider = new NodeCryptoProvider() +export const defaultPlatform: NodePlatform = new NodePlatform() +export const defaultCryptoProvider: NodeCryptoProvider = new NodeCryptoProvider() diff --git a/packages/test/src/platform.web.ts b/packages/test/src/platform.web.ts index eea14331..32a10db3 100644 --- a/packages/test/src/platform.web.ts +++ b/packages/test/src/platform.web.ts @@ -1,4 +1,4 @@ import { WebCryptoProvider, WebPlatform } from '@mtcute/web' -export const defaultPlatform = new WebPlatform() -export const defaultCryptoProvider = new WebCryptoProvider() +export const defaultPlatform: WebPlatform = new WebPlatform() +export const defaultCryptoProvider: WebCryptoProvider = new WebCryptoProvider() diff --git a/packages/test/src/schema.ts b/packages/test/src/schema.ts index 8f8fc021..f38c62b8 100644 --- a/packages/test/src/schema.ts +++ b/packages/test/src/schema.ts @@ -7,7 +7,10 @@ let _cachedEntriesMap: Map | null = null let _cachedUnionsMap: Map | null = null /** @internal */ -export function getEntriesMap() { +export function getEntriesMap(): { + entries: Map + unions: Map +} { if (_cachedEntriesMap) { return { entries: _cachedEntriesMap, diff --git a/packages/test/src/storage.ts b/packages/test/src/storage.ts index 72a47cb3..e10142b6 100644 --- a/packages/test/src/storage.ts +++ b/packages/test/src/storage.ts @@ -52,7 +52,12 @@ export class StubMemoryTelegramStorage extends MemoryStorage { } } - decryptOutgoingMessage(crypto: ICryptoProvider, data: Uint8Array, dcId: number, tempIndex?: number | undefined) { + decryptOutgoingMessage( + crypto: ICryptoProvider, + data: Uint8Array, + dcId: number, + tempIndex?: number | undefined, + ): Uint8Array { const key = tempIndex ? this.authKeys.getTemp(dcId, tempIndex, Date.now()) : this.authKeys.get(dcId) if (!key) { diff --git a/packages/test/src/storage/auth-keys.ts b/packages/test/src/storage/auth-keys.ts index f995978f..fc333630 100644 --- a/packages/test/src/storage/auth-keys.ts +++ b/packages/test/src/storage/auth-keys.ts @@ -19,7 +19,7 @@ function fixBuffer(buf: Uint8Array | null): Uint8Array | null { return typeof Buffer !== 'undefined' && buf instanceof Buffer ? new Uint8Array(buf) : buf } -export function testAuthKeysRepository(repo: IAuthKeysRepository) { +export function testAuthKeysRepository(repo: IAuthKeysRepository): void { const key2 = new Uint8Array(256).fill(0x42) const key3 = new Uint8Array(256).fill(0x43) diff --git a/packages/test/src/storage/key-value.ts b/packages/test/src/storage/key-value.ts index ee1e82d6..8f9ba345 100644 --- a/packages/test/src/storage/key-value.ts +++ b/packages/test/src/storage/key-value.ts @@ -17,7 +17,7 @@ function fixBuffer(buf: Uint8Array | null): Uint8Array | null { return typeof Buffer !== 'undefined' && buf instanceof Buffer ? new Uint8Array(buf) : buf } -export function testKeyValueRepository(repo: IKeyValueRepository, driver: IStorageDriver) { +export function testKeyValueRepository(repo: IKeyValueRepository, driver: IStorageDriver): void { describe('key-value', () => { afterEach(() => repo.deleteAll()) diff --git a/packages/test/src/storage/peers.ts b/packages/test/src/storage/peers.ts index 8c08e0e8..e93a83b5 100644 --- a/packages/test/src/storage/peers.ts +++ b/packages/test/src/storage/peers.ts @@ -28,7 +28,7 @@ function fixPeerInfo(peer: IPeersRepository.PeerInfo | null): IPeersRepository.P } } -export function testPeersRepository(repo: IPeersRepository, driver: IStorageDriver) { +export function testPeersRepository(repo: IPeersRepository, driver: IStorageDriver): void { const stubPeerUser: IPeersRepository.PeerInfo = { id: 123123, accessHash: '123|456', diff --git a/packages/test/src/storage/ref-messages.ts b/packages/test/src/storage/ref-messages.ts index aa4c0c5c..fb3ac812 100644 --- a/packages/test/src/storage/ref-messages.ts +++ b/packages/test/src/storage/ref-messages.ts @@ -11,7 +11,7 @@ export function fakeRefMessagesRepository(): IReferenceMessagesRepository { } } -export function testRefMessagesRepository(repo: IReferenceMessagesRepository, driver: IStorageDriver) { +export function testRefMessagesRepository(repo: IReferenceMessagesRepository, driver: IStorageDriver): void { describe('IReferenceMessagesRepository', () => { afterEach(() => repo.deleteAll()) diff --git a/packages/test/src/transport.ts b/packages/test/src/transport.ts index 5af91daa..83e82c68 100644 --- a/packages/test/src/transport.ts +++ b/packages/test/src/transport.ts @@ -21,7 +21,7 @@ export class StubTelegramTransport extends EventEmitter implements ITelegramTran } } - _state = TransportState.Idle + _state: TransportState = TransportState.Idle _currentDc: tl.RawDcOption | null = null _crypto!: ICryptoProvider _log!: Logger diff --git a/packages/tl-runtime/src/reader.ts b/packages/tl-runtime/src/reader.ts index f6a79cf3..0a721bc8 100644 --- a/packages/tl-runtime/src/reader.ts +++ b/packages/tl-runtime/src/reader.ts @@ -98,8 +98,8 @@ export class TlBinaryReader { int53(): number { // inlined toNumber from Long - const res - = (this.dataView.getInt32(this.pos, true) >>> 0) + TWO_PWR_32_DBL * this.dataView.getInt32(this.pos + 4, true) + const res = (this.dataView.getInt32(this.pos, true) >>> 0) + + TWO_PWR_32_DBL * this.dataView.getInt32(this.pos + 4, true) this.pos += 8 return res @@ -176,7 +176,7 @@ export class TlBinaryReader { return TlBinaryReader.platform.utf8Decode(this.bytes()) } - object(id = this.uint()): unknown { + object(id: number = this.uint()): unknown { if (id === 0x1CB5C415 /* vector */) { return this.vector(this.object, true) } @@ -204,7 +204,7 @@ export class TlBinaryReader { return reader(this) } - vector(reader = this.object, bare = false): unknown[] { + vector(reader: (id?: number) => unknown = this.object, bare = false): unknown[] { if (!bare) { const uint = this.uint() diff --git a/packages/tl-utils/src/codegen/reader.ts b/packages/tl-utils/src/codegen/reader.ts index f9c3e78b..4a02be8d 100644 --- a/packages/tl-utils/src/codegen/reader.ts +++ b/packages/tl-utils/src/codegen/reader.ts @@ -47,7 +47,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: ReaderCodegenOptions = DEFAULT_OPTIONS): string { const { variableName, includeFlags } = { ...DEFAULT_OPTIONS, ...params } if (entry.id === 0) entry.id = computeConstructorIdFromEntry(entry) @@ -169,7 +169,10 @@ export function generateReaderCodeForTlEntry(entry: TlEntry, params = DEFAULT_OP * @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: ReaderCodegenOptions = DEFAULT_OPTIONS, +): string { const { variableName, includeMethods } = { ...DEFAULT_OPTIONS, ...params } let ret = `var ${variableName}={\n` diff --git a/packages/tl-utils/src/codegen/writer.ts b/packages/tl-utils/src/codegen/writer.ts index 6319239b..f1309350 100644 --- a/packages/tl-utils/src/codegen/writer.ts +++ b/packages/tl-utils/src/codegen/writer.ts @@ -57,7 +57,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: WriterCodegenOptions = DEFAULT_OPTIONS): string { const { bare, includeFlags, variableName } = { ...DEFAULT_OPTIONS, ...params, @@ -181,7 +181,10 @@ export function generateWriterCodeForTlEntry(entry: TlEntry, params = DEFAULT_OP * @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: WriterCodegenOptions = DEFAULT_OPTIONS, +): string { const { includePrelude, variableName, includeStaticSizes } = { ...DEFAULT_OPTIONS, ...params, diff --git a/packages/tl-utils/src/utils.ts b/packages/tl-utils/src/utils.ts index 57a2fa47..d25791c8 100644 --- a/packages/tl-utils/src/utils.ts +++ b/packages/tl-utils/src/utils.ts @@ -59,7 +59,7 @@ export function groupTlEntriesByNamespace(entries: TlEntry[]): Record { const headers = { 'cookie': `stel_dev_layer=${layer}`, @@ -473,7 +473,7 @@ export async function fetchDocumentation( return ret } -export function applyDocumentation(schema: TlFullSchema, docs: CachedDocumentation) { +export function applyDocumentation(schema: TlFullSchema, docs: CachedDocumentation): void { for (let i = 0; i < 2; i++) { const kind = i === 0 ? 'classes' : 'methods' diff --git a/packages/tl/scripts/process-descriptions-yaml.ts b/packages/tl/scripts/process-descriptions-yaml.ts index 99acdada..62721049 100644 --- a/packages/tl/scripts/process-descriptions-yaml.ts +++ b/packages/tl/scripts/process-descriptions-yaml.ts @@ -48,7 +48,7 @@ function unwrapMaybe(what: MaybeOverwrite, has: boolean): string | undefined { return undefined } -export function applyDescriptionsYamlFile(input: CachedDocumentation, yaml: unknown) { +export function applyDescriptionsYamlFile(input: CachedDocumentation, yaml: unknown): CachedDocumentation { const { objects: byObjects, arguments: byArguments, regex: byRegex } = yaml as DescriptionsYaml // first create an index of all classes and methods diff --git a/packages/wasm/src/index.ts b/packages/wasm/src/index.ts index 8ac66512..aaf9b9f9 100644 --- a/packages/wasm/src/index.ts +++ b/packages/wasm/src/index.ts @@ -171,7 +171,7 @@ export function ige256Decrypt(data: Uint8Array, key: Uint8Array, iv: Uint8Array) * * > **Note**: `freeCtr256` must be called on the returned context when it's no longer needed */ -export function createCtr256(key: Uint8Array, iv: Uint8Array) { +export function createCtr256(key: Uint8Array, iv: Uint8Array): number { getUint8Memory().set(key, sharedKeyPtr) getUint8Memory().set(iv, sharedIvPtr) @@ -181,7 +181,7 @@ export function createCtr256(key: Uint8Array, iv: Uint8Array) { /** * Release a context for AES-CTR-256 en/decryption */ -export function freeCtr256(ctx: number) { +export function freeCtr256(ctx: number): void { wasm.ctr256_free(ctx) } diff --git a/packages/web/src/idb/driver.ts b/packages/web/src/idb/driver.ts index a35d7a1f..0885f7b8 100644 --- a/packages/web/src/idb/driver.ts +++ b/packages/web/src/idb/driver.ts @@ -134,7 +134,7 @@ export class IdbStorageDriver extends BaseStorageDriver { }) } - async _save() { + async _save(): Promise { if (this._pendingWritesOses.size === 0) return const writes = this._pendingWrites diff --git a/packages/web/src/idb/index.ts b/packages/web/src/idb/index.ts index 39bfc51a..ae266c45 100644 --- a/packages/web/src/idb/index.ts +++ b/packages/web/src/idb/index.ts @@ -15,11 +15,11 @@ export { IdbStorageDriver } from './driver.js' * recommended over local storage based one. */ export class IdbStorage implements IMtStorageProvider { - readonly driver - readonly kv - readonly authKeys - readonly peers - readonly refMessages + readonly driver: IdbStorageDriver + readonly kv: IdbKvRepository + readonly authKeys: IdbAuthKeysRepository + readonly peers: IdbPeersRepository + readonly refMessages: IdbRefMsgRepository constructor(readonly dbName: string) { this.driver = new IdbStorageDriver(this.dbName) diff --git a/packages/web/src/platform.ts b/packages/web/src/platform.ts index e477fafb..baa3075f 100644 --- a/packages/web/src/platform.ts +++ b/packages/web/src/platform.ts @@ -29,7 +29,7 @@ export class WebPlatform implements ICorePlatform { return null } - onNetworkChanged(fn: (connected: boolean) => void) { + onNetworkChanged(fn: (connected: boolean) => void): () => void { if (!('onLine' in navigator)) return () => {} const onlineHandler = () => fn(navigator.onLine) diff --git a/packages/web/src/websocket.ts b/packages/web/src/websocket.ts index fa2edfbf..be33290a 100644 --- a/packages/web/src/websocket.ts +++ b/packages/web/src/websocket.ts @@ -190,5 +190,5 @@ export abstract class BaseWebSocketTransport extends EventEmitter implements ITe } export class WebSocketTransport extends BaseWebSocketTransport { - _packetCodec = new ObfuscatedPacketCodec(new IntermediatePacketCodec()) + _packetCodec: ObfuscatedPacketCodec = new ObfuscatedPacketCodec(new IntermediatePacketCodec()) } diff --git a/tsconfig.json b/tsconfig.json index 7900d727..c375fb92 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,7 +18,6 @@ "deno/ns", "vite/client" ], - "allowJs": true, "strict": true, "noImplicitAny": true, "noImplicitThis": true, @@ -29,6 +28,7 @@ "stripInternal": false, "allowSyntheticDefaultImports": true, "esModuleInterop": true, + "isolatedDeclarations": true, "isolatedModules": true, "skipLibCheck": true },