diff --git a/package.json b/package.json index 9e3d82610..a070e0a20 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,8 @@ "check": "tsc && stylelint \"**/*.{css,scss}\" && eslint . --ext .ts,.tsx,.js --ignore-pattern src/lib/gramjs", "check:fix": "npm run check -- --fix", "tl:rehash": "node ./dev/tlHash.js", - "gramjs:tl": "node ./src/lib/gramjs/tl/generateModules.js", - "gramjs:lint": "eslint src/lib/gramjs --ext .ts,.tsx,.js", + "gramjs:tl": "tsx ./src/lib/gramjs/tl/generateModules.ts", + "gramjs:lint": "cd src/lib/gramjs && eslint --ext .ts,.tsx,.js .", "gramjs:lint:fix": "npm run gramjs:lint -- --fix", "lang:ts": "tsx ./dev/generateLangTypes.js", "lang:initial": "tsx ./dev/generateInitialLangFallback.js", diff --git a/src/api/gramjs/apiBuilders/statistics.ts b/src/api/gramjs/apiBuilders/statistics.ts index 78312bf5c..18bdf455e 100644 --- a/src/api/gramjs/apiBuilders/statistics.ts +++ b/src/api/gramjs/apiBuilders/statistics.ts @@ -221,7 +221,7 @@ function buildStatisticsOverview({ current, previous }: GramJs.StatsAbsValueAndP return { current, change, - ...(previous && { percentage: (change ? ((Math.abs(change) / previous) * 100) : 0).toFixed(2) }), + percentage: (change ? ((Math.abs(change) / previous) * 100) : 0).toFixed(2), }; } diff --git a/src/api/gramjs/localDb.ts b/src/api/gramjs/localDb.ts index bb2d0788e..871a506b2 100644 --- a/src/api/gramjs/localDb.ts +++ b/src/api/gramjs/localDb.ts @@ -1,7 +1,5 @@ import BigInt from 'big-integer'; -import { constructors } from '../../lib/gramjs/tl'; - -import type { Api as GramJs } from '../../lib/gramjs'; +import { Api as GramJs } from '../../lib/gramjs'; import { DATA_BROADCAST_CHANNEL_NAME, DEBUG } from '../../config'; import { throttle } from '../../util/schedulers'; @@ -82,7 +80,7 @@ function convertToVirtualClass(value: any): any { const path = value.className.split('.'); const VirtualClass = path.reduce((acc: any, field: string) => { return acc[field]; - }, constructors); + }, GramJs); const valueOmited = omitVirtualClassFields(value); const valueConverted = Object.keys(valueOmited).reduce((acc, key) => { diff --git a/src/api/gramjs/methods/auth.ts b/src/api/gramjs/methods/auth.ts index 240112b12..57e1430e8 100644 --- a/src/api/gramjs/methods/auth.ts +++ b/src/api/gramjs/methods/auth.ts @@ -1,4 +1,4 @@ -import { errors } from '../../../lib/gramjs'; +import { FloodWaitError, RPCError } from '../../../lib/gramjs/errors'; import type { ApiUpdateAuthorizationState, @@ -87,11 +87,13 @@ export function onRequestQrCode(qrCode: { token: Buffer; expires: number }) { export function onAuthError(err: Error) { let message: string; - if (err instanceof errors.FloodWaitError) { + if (err instanceof FloodWaitError) { const hours = Math.ceil(Number(err.seconds) / 60 / 60); message = `Too many attempts. Try again in ${hours > 1 ? `${hours} hours` : 'an hour'}`; + } else if (err instanceof RPCError) { + message = ApiErrors[err.errorMessage]; } else { - message = ApiErrors[err.message]; + message = err.message; } if (!message) { diff --git a/src/api/gramjs/methods/chats.ts b/src/api/gramjs/methods/chats.ts index cde5825f7..6101ad0d3 100644 --- a/src/api/gramjs/methods/chats.ts +++ b/src/api/gramjs/methods/chats.ts @@ -1,5 +1,6 @@ import BigInt from 'big-integer'; import { Api as GramJs } from '../../../lib/gramjs'; +import { RPCError } from '../../../lib/gramjs/errors'; import type { ApiChat, @@ -1460,11 +1461,12 @@ export async function addChatMembers(chat: ApiChat, users: ApiUser[]) { if (addChatUsersResult) { return addChatUsersResult.flat().filter(Boolean); } - } catch (err) { + } catch (err: unknown) { + const message = err instanceof RPCError ? err.errorMessage : (err as Error).message; sendApiUpdate({ '@type': 'error', error: { - message: (err as Error).message, + message, }, }); } diff --git a/src/api/gramjs/methods/client.ts b/src/api/gramjs/methods/client.ts index 416978877..8bab90fdb 100644 --- a/src/api/gramjs/methods/client.ts +++ b/src/api/gramjs/methods/client.ts @@ -1,9 +1,11 @@ import { Api as GramJs, sessions, + type Update, } from '../../../lib/gramjs'; import type { TwoFaParams, TwoFaPasswordParams } from '../../../lib/gramjs/client/2fa'; import TelegramClient from '../../../lib/gramjs/client/TelegramClient'; +import { RPCError } from '../../../lib/gramjs/errors'; import { Logger as GramJsLogger } from '../../../lib/gramjs/extensions/index'; import type { ThreadId } from '../../../types'; @@ -54,7 +56,7 @@ const DEFAULT_PLATFORM = 'Unknown platform'; GramJsLogger.setLevel(DEBUG_GRAMJS ? 'debug' : 'warn'); -const gramJsUpdateEventBuilder = { build: (update: object) => update }; +const gramJsUpdateEventBuilder = { build: (update: Update) => update }; const CHAT_ABORT_CONTROLLERS = new Map(); const ABORT_CONTROLLERS = new Map(); @@ -83,7 +85,7 @@ export async function init(initialArgs: ApiInitialArgs) { client = new TelegramClient( session, - process.env.TELEGRAM_API_ID, + Number(process.env.TELEGRAM_API_ID), process.env.TELEGRAM_API_HASH, { deviceModel: navigator.userAgent || userAgent || DEFAULT_USER_AGENT, @@ -194,7 +196,7 @@ export function getClient() { return client; } -function onSessionUpdate(sessionData: ApiSessionData) { +function onSessionUpdate(sessionData?: ApiSessionData) { sendApiUpdate({ '@type': 'updateSession', sessionData, @@ -330,27 +332,29 @@ export async function downloadMedia( ) { try { return (await downloadMediaWithClient(args, client, onProgress)); - } catch (err: any) { - if (err.message.startsWith('FILE_REFERENCE')) { - const isFileReferenceRepaired = await repairFileReference({ url: args.url }); - if (isFileReferenceRepaired) { - return downloadMediaWithClient(args, client, onProgress); + } catch (err: unknown) { + if (err instanceof RPCError) { + if (err.errorMessage.startsWith('FILE_REFERENCE')) { + const isFileReferenceRepaired = await repairFileReference({ url: args.url }); + if (isFileReferenceRepaired) { + return downloadMediaWithClient(args, client, onProgress); + } + + if (DEBUG) { + // eslint-disable-next-line no-console + console.error('Failed to repair file reference', args.url); + } } - if (DEBUG) { - // eslint-disable-next-line no-console - console.error('Failed to repair file reference', args.url); + if (err.errorMessage === 'FILE_ID_INVALID' && args.url.includes('avatar')) { + if (DEBUG) { + // eslint-disable-next-line no-console + console.warn('Inaccessible avatar image', args.url); + } + return undefined; } } - if (err.message === 'FILE_ID_INVALID' && args.url.includes('avatar')) { - if (DEBUG) { - // eslint-disable-next-line no-console - console.warn('Inaccessible avatar image', args.url); - } - return undefined; - } - if (DEBUG) { // eslint-disable-next-line no-console console.error('Failed to download media', args.url, err); @@ -416,14 +420,13 @@ export async function fetchCurrentUser() { } export function dispatchErrorUpdate(err: Error, request: T) { - const isSlowMode = err.message.startsWith('A wait of') && ( + const message = err instanceof RPCError ? err.errorMessage : err.message; + const isSlowMode = message === 'FLOOD' && ( request instanceof GramJs.messages.SendMessage || request instanceof GramJs.messages.SendMedia || request instanceof GramJs.messages.SendMultiMedia ); - const { message } = err; - sendApiUpdate({ '@type': 'error', error: { @@ -442,7 +445,7 @@ async function handleTerminatedSession() { shouldThrow: true, }); } catch (err: any) { - if (err.message === 'AUTH_KEY_UNREGISTERED' || err.message === 'SESSION_REVOKED') { + if (err.errorMessage === 'AUTH_KEY_UNREGISTERED' || err.errorMessage === 'SESSION_REVOKED') { sendApiUpdate({ '@type': 'updateConnectionState', connectionState: 'connectionStateBroken', diff --git a/src/api/gramjs/methods/media.ts b/src/api/gramjs/methods/media.ts index 21796638f..0b970d962 100644 --- a/src/api/gramjs/methods/media.ts +++ b/src/api/gramjs/methods/media.ts @@ -1,6 +1,7 @@ +import bigInt from 'big-integer'; import { Api as GramJs } from '../../../lib/gramjs'; -import type { TelegramClient } from '../../../lib/gramjs'; +import type { SizeType, TelegramClient } from '../../../lib/gramjs'; import type { ApiOnProgress, ApiParsedMedia } from '../../types'; import { ApiMediaFormat, @@ -88,15 +89,16 @@ async function download( } = parsed; if (entityType === 'staticMap') { - const accessHash = entityId; + const accessHash = bigInt(entityId); const parsedParams = new URLSearchParams(params); - const long = parsedParams.get('long'); - const lat = parsedParams.get('lat'); - const w = parsedParams.get('w'); - const h = parsedParams.get('h'); - const zoom = parsedParams.get('zoom'); - const scale = parsedParams.get('scale'); - const accuracyRadius = parsedParams.get('accuracy_radius'); + const long = Number(parsedParams.get('long')); + const lat = Number(parsedParams.get('lat')); + const w = Number(parsedParams.get('w')); + const h = Number(parsedParams.get('h')); + const zoom = Number(parsedParams.get('zoom')); + const scale = Number(parsedParams.get('scale')); + const accuracyRadiusStr = parsedParams.get('accuracy_radius'); + const accuracyRadius = accuracyRadiusStr ? Number(accuracyRadiusStr) : undefined; const data = await client.downloadStaticMap(accessHash, long, lat, w, h, zoom, scale, accuracyRadius); return { @@ -167,13 +169,13 @@ async function download( return { mimeType, data, fullSize }; } else if (entityType === 'stickerSet') { - const data = await client.downloadStickerSetThumb(entity); - const mimeType = getMimeType(data); + const data = await client.downloadStickerSetThumb(entity as GramJs.StickerSet); + const mimeType = data && getMimeType(data); return { mimeType, data }; } else { - const data = await client.downloadProfilePhoto(entity, mediaMatchType === 'profile'); - const mimeType = getMimeType(data); + const data = await client.downloadProfilePhoto(entity as GramJs.Chat | GramJs.User, mediaMatchType === 'profile'); + const mimeType = data && getMimeType(data); return { mimeType, data }; } @@ -181,8 +183,12 @@ async function download( // eslint-disable-next-line no-async-without-await/no-async-without-await async function parseMedia( - data: Buffer, mediaFormat: ApiMediaFormat, mimeType?: string, + data: Buffer | File, mediaFormat: ApiMediaFormat, mimeType?: string, ): Promise { + if (data instanceof File) { + return data; + } + switch (mediaFormat) { case ApiMediaFormat.BlobUrl: return new Blob([data], { type: mimeType }); @@ -246,7 +252,7 @@ export function parseMediaUrl(url: string) { let entityType: EntityType; const params = mediaMatch[3]; - const sizeType = params?.replace('?size=', '') || undefined; + const sizeType = params?.replace('?size=', '') as SizeType || undefined; if (mediaMatch[1] === 'avatar' || mediaMatch[1] === 'profile') { entityType = getEntityTypeById(entityId); diff --git a/src/api/gramjs/methods/messages.ts b/src/api/gramjs/methods/messages.ts index b64c0f731..c11b5c847 100644 --- a/src/api/gramjs/methods/messages.ts +++ b/src/api/gramjs/methods/messages.ts @@ -1,5 +1,6 @@ import BigInt from 'big-integer'; import { Api as GramJs } from '../../../lib/gramjs'; +import { RPCError } from '../../../lib/gramjs/errors'; import type { ThreadId, WebPageMediaSize } from '../../../types'; import type { @@ -153,7 +154,7 @@ export async function fetchMessages({ abortControllerThreadId: threadId, }); } catch (err: any) { - if (err.message === 'CHANNEL_PRIVATE') { + if (err.errorMessage === 'CHANNEL_PRIVATE') { sendApiUpdate({ '@type': 'updateChat', id: chat.id, @@ -421,7 +422,7 @@ export function sendMessage( }); if (update) handleLocalMessageUpdate(localMessage, update); } catch (error: any) { - if (error.message === 'PRIVACY_PREMIUM_REQUIRED') { + if (error.errorMessage === 'PRIVACY_PREMIUM_REQUIRED') { sendApiUpdate({ '@type': 'updateRequestUserUpdate', id: chat.id }); } @@ -1786,8 +1787,8 @@ export async function reportSponsoredMessage({ } return buildApiSponsoredMessageReportResult(result); - } catch (err) { - if (err instanceof Error && err.message === 'PREMIUM_ACCOUNT_REQUIRED') { + } catch (err: unknown) { + if (err instanceof RPCError && err.errorMessage === 'PREMIUM_ACCOUNT_REQUIRED') { return { type: 'premiumRequired' as const, }; diff --git a/src/api/gramjs/methods/phoneCallState.ts b/src/api/gramjs/methods/phoneCallState.ts index 5eb27b15a..b84d6dfb9 100644 --- a/src/api/gramjs/methods/phoneCallState.ts +++ b/src/api/gramjs/methods/phoneCallState.ts @@ -1,8 +1,10 @@ import type bigInt from 'big-integer'; import BigInt from 'big-integer'; -import AuthKey from '../../../lib/gramjs/crypto/AuthKey'; -import Logger from '../../../lib/gramjs/extensions/Logger'; -import Helpers from '../../../lib/gramjs/Helpers'; +import { AuthKey } from '../../../lib/gramjs/crypto/AuthKey'; +import { Logger } from '../../../lib/gramjs/extensions'; +import { + convertToLittle, getByteArray, modExp, readBigIntFromBuffer, sha1, sha256, +} from '../../../lib/gramjs/Helpers'; import MTProtoState from '../../../lib/gramjs/network/MTProtoState'; type DhConfig = { @@ -39,58 +41,62 @@ class PhoneCallState { } async requestCall({ p, g, random }: DhConfig) { - const pBN = Helpers.readBigIntFromBuffer(Buffer.from(p), false); - const randomBN = Helpers.readBigIntFromBuffer(Buffer.from(random), false); + const pBN = readBigIntFromBuffer(Buffer.from(p), false); + const randomBN = readBigIntFromBuffer(Buffer.from(random), false); - const gA = Helpers.modExp(BigInt(g), randomBN, pBN); + const gA = modExp(BigInt(g), randomBN, pBN); this.gA = gA; this.p = pBN; this.random = randomBN; - const gAHash: Buffer = await Helpers.sha256(Helpers.getByteArray(gA)); + const gAHash: Buffer = await sha256(getByteArray(gA)); return Array.from(gAHash); } acceptCall({ p, g, random }: DhConfig) { - const pLast = Helpers.readBigIntFromBuffer(p, false); - const randomLast = Helpers.readBigIntFromBuffer(random, false); + const pLast = readBigIntFromBuffer(p, false); + const randomLast = readBigIntFromBuffer(random, false); - const gB = Helpers.modExp(BigInt(g), randomLast, pLast); + const gB = modExp(BigInt(g), randomLast, pLast); this.gB = gB; this.p = pLast; this.random = randomLast; - return Array.from(Helpers.getByteArray(gB)); + return Array.from(getByteArray(gB)); } async confirmCall(gAOrB: number[], emojiData: Uint16Array, emojiOffsets: number[]) { - if (this.isOutgoing) { - this.gB = Helpers.readBigIntFromBuffer(Buffer.from(gAOrB), false); - } else { - this.gA = Helpers.readBigIntFromBuffer(Buffer.from(gAOrB), false); + if (!this.random || !this.p) { + throw new Error('Values not set'); } - const authKey = Helpers.modExp( + + if (this.isOutgoing) { + this.gB = readBigIntFromBuffer(Buffer.from(gAOrB), false); + } else { + this.gA = readBigIntFromBuffer(Buffer.from(gAOrB), false); + } + const authKey = modExp( !this.isOutgoing ? this.gA : this.gB, this.random, this.p, ); - const fingerprint: Buffer = await Helpers.sha1(Helpers.getByteArray(authKey)); - const keyFingerprint = Helpers.readBigIntFromBuffer(fingerprint.slice(-8).reverse(), false); + const fingerprint: Buffer = await sha1(getByteArray(authKey)); + const keyFingerprint = readBigIntFromBuffer(fingerprint.slice(-8).reverse(), false); const emojis = await generateEmojiFingerprint( - Helpers.getByteArray(authKey), - Helpers.getByteArray(this.gA), + getByteArray(authKey), + getByteArray(this.gA!), emojiData, emojiOffsets, ); const key = new AuthKey(); - await key.setKey(Helpers.getByteArray(authKey)); + await key.setKey(getByteArray(authKey)); this.state = new MTProtoState(key, new Logger(), true, this.isOutgoing); this.resolveState!(); - return { gA: Array.from(Helpers.getByteArray(this.gA)), keyFingerprint: keyFingerprint.toString(), emojis }; + return { gA: Array.from(getByteArray(this.gA!)), keyFingerprint: keyFingerprint.toString(), emojis }; } async encode(data: string) { @@ -99,7 +105,7 @@ class PhoneCallState { const seqArray = new Uint32Array(1); seqArray[0] = this.seq++; const encodedData = await this.state.encryptMessageData( - Buffer.concat([Helpers.convertToLittle(seqArray), Buffer.from(data)]), + Buffer.concat([convertToLittle(seqArray), Buffer.from(data)]), ); return Array.from(encodedData); } @@ -132,7 +138,7 @@ function computeEmojiIndex(bytes: Uint8Array) { async function generateEmojiFingerprint( authKey: Uint8Array, gA: Uint8Array, emojiData: Uint16Array, emojiOffsets: number[], ) { - const hash = await Helpers.sha256(Buffer.concat([new Uint8Array(authKey), new Uint8Array(gA)])); + const hash = await sha256(Buffer.concat([new Uint8Array(authKey), new Uint8Array(gA)])); const result = []; const emojiCount = emojiOffsets.length - 1; const kPartSize = 8; diff --git a/src/api/gramjs/methods/settings.ts b/src/api/gramjs/methods/settings.ts index cc9cb3a29..f4f215f13 100644 --- a/src/api/gramjs/methods/settings.ts +++ b/src/api/gramjs/methods/settings.ts @@ -1,11 +1,11 @@ import BigInt from 'big-integer'; import { Api as GramJs } from '../../../lib/gramjs'; +import { RPCError } from '../../../lib/gramjs/errors'; import type { LANG_PACKS } from '../../../config'; import type { ApiAppConfig, ApiConfig, - ApiError, ApiInputPrivacyRules, ApiLanguage, ApiNotifyException, @@ -77,17 +77,15 @@ export async function checkUsername(username: string) { }); return { result, error: undefined }; - } catch (error) { - const errorMessage = (error as ApiError).message; - - if (ACCEPTABLE_USERNAME_ERRORS.has(errorMessage)) { + } catch (err: unknown) { + if (err instanceof RPCError && ACCEPTABLE_USERNAME_ERRORS.has(err.errorMessage)) { return { result: false, - error: errorMessage, + error: err.errorMessage, }; } - throw error; + throw err; } } diff --git a/src/api/gramjs/updates/mtpUpdateHandler.ts b/src/api/gramjs/updates/mtpUpdateHandler.ts index a42ad1b5c..e659c2496 100644 --- a/src/api/gramjs/updates/mtpUpdateHandler.ts +++ b/src/api/gramjs/updates/mtpUpdateHandler.ts @@ -1,4 +1,5 @@ -import { Api as GramJs, connection } from '../../../lib/gramjs'; +import { Api as GramJs, type Update } from '../../../lib/gramjs'; +import { UpdateConnectionState, UpdateServerTimeOffset } from '../../../lib/gramjs/network'; import type { GroupCallConnectionData } from '../../../lib/secret-sauce'; import type { @@ -81,33 +82,29 @@ import { sendApiUpdate } from './apiUpdateEmitter'; import { processMessageAndUpdateThreadInfo } from './entityProcessor'; import LocalUpdatePremiumFloodWait from './UpdatePremiumFloodWait'; -import { LocalUpdateChannelPts, LocalUpdatePts, type UpdatePts } from './UpdatePts'; - -export type Update = ( - (GramJs.TypeUpdate | GramJs.TypeUpdates) & { _entities?: (GramJs.TypeUser | GramJs.TypeChat)[] } -) | typeof connection.UpdateConnectionState | UpdatePts | LocalUpdatePremiumFloodWait; +import { LocalUpdateChannelPts, LocalUpdatePts } from './UpdatePts'; const sentMessageIds = new Set(); export function updater(update: Update) { - if (update instanceof connection.UpdateServerTimeOffset) { + if (update instanceof UpdateServerTimeOffset) { setServerTimeOffset(update.timeOffset); sendApiUpdate({ '@type': 'updateServerTimeOffset', serverTimeOffset: update.timeOffset, }); - } else if (update instanceof connection.UpdateConnectionState) { + } else if (update instanceof UpdateConnectionState) { let connectionState: ApiUpdateConnectionStateType; switch (update.state) { - case connection.UpdateConnectionState.disconnected: + case UpdateConnectionState.disconnected: connectionState = 'connectionStateConnecting'; break; - case connection.UpdateConnectionState.broken: + case UpdateConnectionState.broken: connectionState = 'connectionStateBroken'; break; - case connection.UpdateConnectionState.connected: + case UpdateConnectionState.connected: default: connectionState = 'connectionStateReady'; break; diff --git a/src/api/gramjs/updates/updateManager.ts b/src/api/gramjs/updates/updateManager.ts index 2b4478b8d..2f355fda9 100644 --- a/src/api/gramjs/updates/updateManager.ts +++ b/src/api/gramjs/updates/updateManager.ts @@ -1,4 +1,4 @@ -import { Api as GramJs } from '../../../lib/gramjs'; +import { Api as GramJs, type Update } from '../../../lib/gramjs'; import { UpdateConnectionState, UpdateServerTimeOffset } from '../../../lib/gramjs/network'; import type { ApiChat } from '../../types'; @@ -11,7 +11,7 @@ import { buildInputEntity, buildMtpPeerId } from '../gramjsBuilders'; import localDb from '../localDb'; import { sendApiUpdate } from './apiUpdateEmitter'; import { processAndUpdateEntities } from './entityProcessor'; -import { type Update, updater } from './mtpUpdateHandler'; +import { updater } from './mtpUpdateHandler'; import { buildLocalUpdatePts, type UpdatePts } from './UpdatePts'; diff --git a/src/api/types/messages.ts b/src/api/types/messages.ts index 826aeccf3..ba266eeca 100644 --- a/src/api/types/messages.ts +++ b/src/api/types/messages.ts @@ -24,7 +24,7 @@ export interface ApiPhotoSize extends ApiDimensions { export interface ApiVideoSize extends ApiDimensions { type: 'u' | 'v'; - videoStartTs: number; + videoStartTs?: number; size: number; } diff --git a/src/api/types/misc.ts b/src/api/types/misc.ts index dea7ca71d..b57b8da4e 100644 --- a/src/api/types/misc.ts +++ b/src/api/types/misc.ts @@ -101,9 +101,9 @@ export interface ApiWebSession { export interface ApiSessionData { mainDcId: number; - isTest?: true; keys: Record; hashes: Record; + isTest?: true; } export type ApiNotifyException = { diff --git a/src/global/actions/api/chats.ts b/src/global/actions/api/chats.ts index 34853175c..96959bf1f 100644 --- a/src/global/actions/api/chats.ts +++ b/src/global/actions/api/chats.ts @@ -2173,7 +2173,7 @@ addActionHandler('toggleForum', async (global, actions, payload): Promise try { result = await callApi('toggleForum', { chat, isEnabled }); } catch (error) { - if ((error as ApiError).message.startsWith('A wait of')) { + if ((error as ApiError).message === 'FLOOD') { actions.showNotification({ message: langProvider.oldTranslate('FloodWait'), tabId }); } else { actions.showDialog({ data: { ...(error as ApiError), hasErrorKey: true }, tabId }); diff --git a/src/global/actions/api/symbols.ts b/src/global/actions/api/symbols.ts index 92fb118ba..cf9eb22b1 100644 --- a/src/global/actions/api/symbols.ts +++ b/src/global/actions/api/symbols.ts @@ -577,7 +577,7 @@ async function loadStickers( 'fetchStickers', { stickerSetInfo }, ); - } catch (error) { + } catch (error: unknown) { if ((error as ApiError).message === 'STICKERSET_INVALID') { Object.values(global.byTabId).forEach(({ id: tabId }) => { actions.showNotification({ diff --git a/src/lib/gramjs/.eslintignore b/src/lib/gramjs/.eslintignore index 7ba75f0d3..ced32892a 100644 --- a/src/lib/gramjs/.eslintignore +++ b/src/lib/gramjs/.eslintignore @@ -1,6 +1,5 @@ -src/lib/gramjs/tl/types-generator/template.js -src/lib/gramjs/tl/api.d.ts -src/lib/gramjs/tl/apiTl.js -src/lib/gramjs/tl/schemaTl.js -src/lib/gramjs/tl/apiTl.full.js -src/lib/gramjs/tl/schemaTl.full.js +tl/api.d.ts +tl/apiTl.ts +tl/schemaTl.ts +tl/apiTl.full.ts +tl/schemaTl.full.ts diff --git a/src/lib/gramjs/.eslintrc b/src/lib/gramjs/.eslintrc index 564b352a4..a16d8c780 100644 --- a/src/lib/gramjs/.eslintrc +++ b/src/lib/gramjs/.eslintrc @@ -3,6 +3,7 @@ "plugins": [ "@typescript-eslint" ], + "root": true, "rules": { "indent": [ "error", diff --git a/src/lib/gramjs/Helpers.js b/src/lib/gramjs/Helpers.js deleted file mode 100644 index 235f37571..000000000 --- a/src/lib/gramjs/Helpers.js +++ /dev/null @@ -1,345 +0,0 @@ -const BigInt = require('big-integer'); -const crypto = require('./crypto/crypto'); - -/** - * converts a buffer to big int - * @param buffer - * @param little - * @param signed - * @returns {bigInt.BigInteger} - */ -function readBigIntFromBuffer(buffer, little = true, signed = false) { - let randBuffer = Buffer.from(buffer); - const bytesNumber = randBuffer.length; - if (little) { - randBuffer = randBuffer.reverse(); - } - let bigInt = BigInt(randBuffer.toString('hex'), 16); - if (signed && Math.floor(bigInt.toString(2).length / 8) >= bytesNumber) { - bigInt = bigInt.subtract(BigInt(2) - .pow(BigInt(bytesNumber * 8))); - } - return bigInt; -} - -/** - * Special case signed little ints - * @param big - * @param number - * @returns {Buffer} - */ -function toSignedLittleBuffer(big, number = 8) { - const bigNumber = BigInt(big); - const byteArray = []; - for (let i = 0; i < number; i++) { - byteArray[i] = bigNumber.shiftRight(8 * i) - .and(255); - } - return Buffer.from(byteArray); -} - -/** - * converts a big int to a buffer - * @param bigInt {bigInt.BigInteger} - * @param bytesNumber - * @param little - * @param signed - * @returns {Buffer} - */ -function readBufferFromBigInt(bigInt, bytesNumber, little = true, signed = false) { - bigInt = BigInt(bigInt); - const bitLength = bigInt.bitLength().toJSNumber(); - - const bytes = Math.ceil(bitLength / 8); - if (bytesNumber < bytes) { - throw new Error('OverflowError: int too big to convert'); - } - if (!signed && bigInt.lesser(BigInt(0))) { - throw new Error('Cannot convert to unsigned'); - } - let below = false; - if (bigInt.lesser(BigInt(0))) { - below = true; - bigInt = bigInt.abs(); - } - - const hex = bigInt.toString(16).padStart(bytesNumber * 2, '0'); - let buffer = Buffer.from(hex, 'hex'); - - if (signed && below) { - buffer[buffer.length - 1] = 256 - buffer[buffer.length - 1]; - for (let i = 0; i < buffer.length - 1; i++) { - buffer[i] = 255 - buffer[i]; - } - } - if (little) { - buffer = buffer.reverse(); - } - - return buffer; -} - -/** - * Generates a random long integer (8 bytes), which is optionally signed - * @returns {BigInteger} - */ -function generateRandomLong(signed = true) { - return readBigIntFromBuffer(generateRandomBytes(8), true, signed); -} - -/** - * .... really javascript - * @param n {number} - * @param m {number} - * @returns {number} - */ -function mod(n, m) { - return ((n % m) + m) % m; -} - -/** - * returns a positive bigInt - * @param n {BigInt} - * @param m {BigInt} - * @returns {BigInt} - */ -function bigIntMod(n, m) { - return ((n.remainder(m)).add(m)).remainder(m); -} - -/** - * Generates a random bytes array - * @param count - * @returns {Buffer} - */ -function generateRandomBytes(count) { - return Buffer.from(crypto.randomBytes(count)); -} - -/** - * Calculate the key based on Telegram guidelines, specifying whether it's the client or not - * @param sharedKey - * @param msgKey - * @param client - * @returns {{iv: Buffer, key: Buffer}} - */ - -/* CONTEST -this is mtproto 1 (mostly used for secret chats) -async function calcKey(sharedKey, msgKey, client) { - const x = client === true ? 0 : 8 - const [sha1a, sha1b, sha1c, sha1d] = await Promise.all([ - sha1(Buffer.concat([msgKey, sharedKey.slice(x, x + 32)])), - sha1(Buffer.concat([sharedKey.slice(x + 32, x + 48), msgKey, sharedKey.slice(x + 48, x + 64)])), - sha1(Buffer.concat([sharedKey.slice(x + 64, x + 96), msgKey])), - sha1(Buffer.concat([msgKey, sharedKey.slice(x + 96, x + 128)])) - ]) - const key = Buffer.concat([sha1a.slice(0, 8), sha1b.slice(8, 20), sha1c.slice(4, 16)]) - const iv = Buffer.concat([sha1a.slice(8, 20), sha1b.slice(0, 8), sha1c.slice(16, 20), sha1d.slice(0, 8)]) - return { - key, - iv - } -} - - */ - -/** - * Generates the key data corresponding to the given nonces - * @param serverNonce - * @param newNonce - * @returns {{key: Buffer, iv: Buffer}} - */ -async function generateKeyDataFromNonce(serverNonce, newNonce) { - serverNonce = toSignedLittleBuffer(serverNonce, 16); - newNonce = toSignedLittleBuffer(newNonce, 32); - const [hash1, hash2, hash3] = await Promise.all([ - sha1(Buffer.concat([newNonce, serverNonce])), - sha1(Buffer.concat([serverNonce, newNonce])), - sha1(Buffer.concat([newNonce, newNonce])), - ]); - const keyBuffer = Buffer.concat([hash1, hash2.slice(0, 12)]); - const ivBuffer = Buffer.concat([hash2.slice(12, 20), hash3, newNonce.slice(0, 4)]); - return { - key: keyBuffer, - iv: ivBuffer, - }; -} - -function convertToLittle(buf) { - const correct = Buffer.alloc(buf.length * 4); - - for (let i = 0; i < buf.length; i++) { - correct.writeUInt32BE(buf[i], i * 4); - } - return correct; -} - -/** - * Calculates the SHA1 digest for the given data - * @param data - * @returns {Promise} - */ -function sha1(data) { - const shaSum = crypto.createHash('sha1'); - shaSum.update(data); - return shaSum.digest(); -} - -/** - * Calculates the SHA256 digest for the given data - * @param data - * @returns {Promise} - */ -function sha256(data) { - const shaSum = crypto.createHash('sha256'); - shaSum.update(data); - return shaSum.digest(); -} - -/** - * Fast mod pow for RSA calculation. a^b % n - * @param a - * @param b - * @param n - * @returns {bigInt.BigInteger} - */ -function modExp(a, b, n) { - a = a.remainder(n); - let result = BigInt.one; - let x = a; - while (b.greater(BigInt.zero)) { - const leastSignificantBit = b.remainder(BigInt(2)); - b = b.divide(BigInt(2)); - if (leastSignificantBit.eq(BigInt.one)) { - result = result.multiply(x); - result = result.remainder(n); - } - x = x.multiply(x); - x = x.remainder(n); - } - return result; -} - -/** - * Gets the arbitrary-length byte array corresponding to the given integer - * @param integer {any} - * @param signed {boolean} - * @returns {Buffer} - */ -function getByteArray(integer, signed = false) { - const bits = integer.toString(2).length; - const byteLength = Math.floor((bits + 8 - 1) / 8); - return readBufferFromBigInt(BigInt(integer), byteLength, false, signed); -} - -/** - * returns a random int from min (inclusive) and max (inclusive) - * @param min - * @param max - * @returns {number} - */ -function getRandomInt(min, max) { - min = Math.ceil(min); - max = Math.floor(max); - return Math.floor(Math.random() * (max - min + 1)) + min; -} - -/** - * Sleeps a specified amount of time - * @param ms time in milliseconds - * @returns {Promise} - */ -const sleep = (ms) => new Promise((resolve) => { - setTimeout(resolve, ms); -}); - -/** - * Helper to export two buffers of same length - * @returns {Buffer} - */ - -function bufferXor(a, b) { - const res = []; - for (let i = 0; i < a.length; i++) { - res.push(a[i] ^ b[i]); - } - return Buffer.from(res); -} - -/** - * Checks if the obj is an array - * @param obj - * @returns {boolean} - */ -/* -CONTEST -we do'nt support array requests anyway -function isArrayLike(obj) { - if (!obj) return false - const l = obj.length - if (typeof l != 'number' || l < 0) return false - if (Math.floor(l) !== l) return false - // fast check - if (l > 0 && !(l - 1 in obj)) return false - // more complete check (optional) - for (let i = 0; i < l; ++i) { - if (!(i in obj)) return false - } - return true -} -*/ - -// Taken from https://stackoverflow.com/questions/18638900/javascript-crc32/18639999#18639999 -function makeCRCTable() { - let c; - const crcTable = []; - for (let n = 0; n < 256; n++) { - c = n; - for (let k = 0; k < 8; k++) { - c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); - } - crcTable[n] = c; - } - return crcTable; -} - -let crcTable; - -function crc32(buf) { - if (!crcTable) { - crcTable = makeCRCTable(); - } - if (!Buffer.isBuffer(buf)) { - buf = Buffer.from(buf); - } - let crc = -1; - - for (let index = 0; index < buf.length; index++) { - const byte = buf[index]; - crc = crcTable[(crc ^ byte) & 0xff] ^ (crc >>> 8); - } - return (crc ^ (-1)) >>> 0; -} - -module.exports = { - readBigIntFromBuffer, - readBufferFromBigInt, - generateRandomLong, - mod, - crc32, - generateRandomBytes, - // calcKey, - generateKeyDataFromNonce, - sha1, - sha256, - bigIntMod, - modExp, - getRandomInt, - sleep, - getByteArray, - // isArrayLike, - toSignedLittleBuffer, - convertToLittle, - bufferXor, -}; diff --git a/src/lib/gramjs/Helpers.ts b/src/lib/gramjs/Helpers.ts new file mode 100644 index 000000000..b77a2ba74 --- /dev/null +++ b/src/lib/gramjs/Helpers.ts @@ -0,0 +1,190 @@ +import BigInt from 'big-integer'; + +import { createHash, randomBytes } from './crypto/crypto'; + +export function readBigIntFromBuffer(buffer: Buffer | number[], little = true, signed = false): BigInt.BigInteger { + let randBuffer = Buffer.from(buffer); + const bytesNumber = randBuffer.length; + if (little) { + randBuffer = randBuffer.reverse(); + } + let bigInt = BigInt(randBuffer.toString('hex'), 16); + if (signed && Math.floor(bigInt.toString(2).length / 8) >= bytesNumber) { + bigInt = bigInt.subtract(BigInt(2) + .pow(BigInt(bytesNumber * 8))); + } + return bigInt; +} + +export function toSignedLittleBuffer(big: BigInt.BigInteger, number = 8) { + const bigNumber = BigInt(big); + const byteArray: number[] = []; + for (let i = 0; i < number; i++) { + byteArray[i] = bigNumber.shiftRight(8 * i) + .and(255) + .toJSNumber(); + } + + return Buffer.from(byteArray); +} + +export function readBufferFromBigInt(bigInt: BigInt.BigInteger, bytesNumber: number, little = true, signed = false) { + const bitLength = bigInt.bitLength().toJSNumber(); + + const bytes = Math.ceil(bitLength / 8); + if (bytesNumber < bytes) { + throw new Error('OverflowError: int too big to convert'); + } + if (!signed && bigInt.lesser(BigInt(0))) { + throw new Error('Cannot convert to unsigned'); + } + let below = false; + if (bigInt.lesser(BigInt(0))) { + below = true; + bigInt = bigInt.abs(); + } + + const hex = bigInt.toString(16).padStart(bytesNumber * 2, '0'); + let buffer = Buffer.from(hex, 'hex'); + + if (signed && below) { + buffer[buffer.length - 1] = 256 - buffer[buffer.length - 1]; + for (let i = 0; i < buffer.length - 1; i++) { + buffer[i] = 255 - buffer[i]; + } + } + if (little) { + buffer = buffer.reverse(); + } + + return buffer; +} + +export function generateRandomLong(signed = true) { + return readBigIntFromBuffer(generateRandomBytes(8), true, signed); +} + +export function mod(n: number, m: number) { + return ((n % m) + m) % m; +} + +export function bigIntMod(n: BigInt.BigInteger, m: BigInt.BigInteger) { + return ((n.remainder(m)).add(m)).remainder(m); +} + +export function generateRandomBytes(count: number) { + return Buffer.from(randomBytes(count)); +} + +export async function generateKeyDataFromNonce( + serverNonceBigInt: BigInt.BigInteger, newNonceBigInt: BigInt.BigInteger, +) { + const serverNonce = toSignedLittleBuffer(serverNonceBigInt, 16); + const newNonce = toSignedLittleBuffer(newNonceBigInt, 32); + const [hash1, hash2, hash3] = await Promise.all([ + sha1(Buffer.concat([newNonce, serverNonce])), + sha1(Buffer.concat([serverNonce, newNonce])), + sha1(Buffer.concat([newNonce, newNonce])), + ]); + const keyBuffer = Buffer.concat([hash1, hash2.slice(0, 12)]); + const ivBuffer = Buffer.concat([hash2.slice(12, 20), hash3, newNonce.slice(0, 4)]); + return { + key: keyBuffer, + iv: ivBuffer, + }; +} + +export function convertToLittle(buf: Uint32Array) { + const correct = Buffer.alloc(buf.length * 4); + + for (let i = 0; i < buf.length; i++) { + correct.writeUInt32BE(buf[i], i * 4); + } + return correct; +} + +export function sha1(data: Buffer): Promise { + const shaSum = createHash('sha1'); + shaSum.update(data); + return shaSum.digest(); +} + +export function sha256(data: Buffer): Promise { + const shaSum = createHash('sha256'); + shaSum.update(data); + return shaSum.digest(); +} + +export function modExp( + a: bigInt.BigInteger, + b: bigInt.BigInteger, + n: bigInt.BigInteger, +) { + a = a.remainder(n); + let result = BigInt.one; + let x = a; + while (b.greater(BigInt.zero)) { + const leastSignificantBit = b.remainder(BigInt(2)); + b = b.divide(BigInt(2)); + if (leastSignificantBit.eq(BigInt.one)) { + result = result.multiply(x); + result = result.remainder(n); + } + x = x.multiply(x); + x = x.remainder(n); + } + return result; +} + +export function getByteArray(integer: BigInt.BigInteger, signed = false) { + const bits = integer.toString(2).length; + const byteLength = Math.floor((bits + 8 - 1) / 8); + return readBufferFromBigInt(BigInt(integer), byteLength, false, signed); +} + +export function getRandomInt(min: number, max: number) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min + 1)) + min; +} + +export function sleep(ms: number) { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); +} + +export function bufferXor(a: Buffer, b: Buffer) { + const res = []; + for (let i = 0; i < a.length; i++) { + res.push(a[i] ^ b[i]); + } + return Buffer.from(res); +} + +// Taken from https://stackoverflow.com/questions/18638900/javascript-crc32/18639999#18639999 +export const CRC32_TABLE = (() => { + let c; + const crcTable = []; + for (let n = 0; n < 256; n++) { + c = n; + for (let k = 0; k < 8; k++) { + c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + crcTable[n] = c; + } + return crcTable; +})(); + +export function crc32(buf: Buffer | string) { + if (!Buffer.isBuffer(buf)) { + buf = Buffer.from(buf); + } + let crc = -1; + + for (let index = 0; index < buf.length; index++) { + const byte = buf[index]; + crc = CRC32_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8); + } + return (crc ^ (-1)) >>> 0; +} diff --git a/src/lib/gramjs/Password.js b/src/lib/gramjs/Password.ts similarity index 78% rename from src/lib/gramjs/Password.js rename to src/lib/gramjs/Password.ts index 053aa744c..6ccbd49bd 100644 --- a/src/lib/gramjs/Password.js +++ b/src/lib/gramjs/Password.ts @@ -1,14 +1,16 @@ -const BigInt = require('big-integer'); -const { constructors } = require('./tl'); -const { +import BigInt from 'big-integer'; + +import { pbkdf2 } from './crypto/crypto'; +import Api from './tl/api'; + +import { + bigIntMod, + generateRandomBytes, + modExp, readBigIntFromBuffer, readBufferFromBigInt, sha256, - bigIntMod, - modExp, - generateRandomBytes, -} = require('./Helpers'); -const crypto = require('./crypto/crypto'); +} from './Helpers'; const SIZE_FOR_HASH = 256; @@ -64,12 +66,8 @@ function checkPrimeAndGoodCheck(prime, g) { } } */ -/** - * - * @param primeBytes{Buffer} - * @param g{number} - */ -function checkPrimeAndGood(primeBytes, g) { + +function checkPrimeAndGood(primeBytes: Buffer, g: number) { const goodPrime = Buffer.from([ 0xC7, 0x1C, 0xAE, 0xB9, 0xC6, 0xB1, 0xC9, 0x04, 0x8E, 0x6C, 0x52, 0x2F, 0x70, 0xF1, 0x3F, 0x73, 0x98, 0x0D, 0x40, 0x23, 0x8E, 0x3E, 0x21, 0xC1, 0x49, 0x34, 0xD0, 0x37, 0x56, 0x3D, 0x93, 0x0F, @@ -97,53 +95,34 @@ function checkPrimeAndGood(primeBytes, g) { // checkPrimeAndGoodCheck(readBigIntFromBuffer(primeBytes, false), g) } -/** - * - * @param number{BigInteger} - * @param p{BigInteger} - * @returns {boolean} - */ -function isGoodLarge(number, p) { +function isGoodLarge(number: BigInt.BigInteger, p: BigInt.BigInteger): boolean { return (number.greater(BigInt(0)) && (p.subtract(number) .greater(BigInt(0)))); } -/** - * - * @param number {Buffer} - * @returns {Buffer} - */ -function numBytesForHash(number) { +function numBytesForHash(number: Buffer): Buffer { return Buffer.concat([Buffer.alloc(SIZE_FOR_HASH - number.length), number]); } -/** - * - * @param g {Buffer} - * @returns {Buffer} - */ -function bigNumForHash(g) { +function bigNumForHash(g: BigInt.BigInteger) { return readBufferFromBigInt(g, SIZE_FOR_HASH, false); } -/** - * - * @param modexp {BigInteger} - * @param prime {BigInteger} - * @returns {Boolean} - */ -function isGoodModExpFirst(modexp, prime) { +function isGoodModExpFirst(modexp: BigInt.BigInteger, prime: BigInt.BigInteger): boolean { const diff = prime.subtract(modexp); const minDiffBitsCount = 2048 - 64; const maxModExpSize = 256; - return !(diff.lesser(BigInt(0)) || diff.bitLength() < minDiffBitsCount - || modexp.bitLength() < minDiffBitsCount - || Math.floor((modexp.bitLength() + 7) / 8) > maxModExpSize); + return !( + diff.lesser(BigInt(0)) + || diff.bitLength().toJSNumber() < minDiffBitsCount + || modexp.bitLength().toJSNumber() < minDiffBitsCount + || Math.floor((modexp.bitLength().toJSNumber() + 7) / 8) > maxModExpSize + ); } -function xor(a, b) { +function xor(a: Buffer, b: Buffer) { const length = Math.min(a.length, b.length); for (let i = 0; i < length; i++) { @@ -153,16 +132,8 @@ function xor(a, b) { return a; } -/** - * - * @param password{Buffer} - * @param salt{Buffer} - * @param iterations{number} - * @returns {*} - */ - -function pbkdf2sha512(password, salt, iterations) { - return crypto.pbkdf2(password, salt, iterations, 64, 'sha512'); +function pbkdf2sha512(password: Buffer, salt: Buffer, iterations: number): any { + return pbkdf2(password, salt, iterations); } /** @@ -171,19 +142,18 @@ function pbkdf2sha512(password, salt, iterations) { * @param password * @returns {Buffer|*} */ -async function computeHash(algo, password) { +async function computeHash( + algo: Api.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow, password: string, +) { const hash1 = await sha256(Buffer.concat([algo.salt1, Buffer.from(password, 'utf-8'), algo.salt1])); const hash2 = await sha256(Buffer.concat([algo.salt2, hash1, algo.salt2])); const hash3 = await pbkdf2sha512(hash2, algo.salt1, 100000); return sha256(Buffer.concat([algo.salt2, hash3, algo.salt2])); } -/** - * - * @param algo {constructors.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow} - * @param password - */ -async function computeDigest(algo, password) { +export async function computeDigest( + algo: Api.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow, password: string, +) { try { checkPrimeAndGood(algo.p, algo.g); } catch (e) { @@ -201,16 +171,21 @@ async function computeDigest(algo, password) { * @param request {constructors.account.Password} * @param password {string} */ -async function computeCheck(request, password) { +export async function computeCheck(request: Api.account.Password, password: string) { const algo = request.currentAlgo; - if (!(algo instanceof constructors.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow)) { - throw new Error(`Unsupported password algorithm ${algo.className}`); + if (!(algo instanceof Api.PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow)) { + throw new Error(`Unsupported password algorithm ${algo?.className}`); } + const srpB = request.srp_B; + const srpId = request.srpId; + if (!srpB || !srpId) { + throw new Error(`Undefined srp_b ${request}`); + } const pwHash = await computeHash(algo, password); const p = readBigIntFromBuffer(algo.p, false); const { g } = algo; - const B = readBigIntFromBuffer(request.srp_B, false); + const B = readBigIntFromBuffer(srpB, false); try { checkPrimeAndGood(algo.p, g); } catch (e) { @@ -221,8 +196,8 @@ async function computeCheck(request, password) { } const x = readBigIntFromBuffer(pwHash, false); const pForHash = numBytesForHash(algo.p); - const gForHash = bigNumForHash(g); - const bForHash = numBytesForHash(request.srp_B); + const gForHash = bigNumForHash(BigInt(g)); + const bForHash = numBytesForHash(srpB); const gX = modExp(BigInt(g), x, p); const k = readBigIntFromBuffer(await sha256(Buffer.concat([pForHash, gForHash])), false); const kgX = bigIntMod(k.multiply(gX), p); @@ -237,12 +212,12 @@ async function computeCheck(request, password) { const aForHash = bigNumForHash(A); const u = readBigIntFromBuffer(await sha256(Buffer.concat([aForHash, bForHash])), false); if (u.greater(BigInt(0))) { - return [a, aForHash, u]; + return { a, aForHash, u }; } } } }; - const [a, aForHash, u] = await generateAndCheckRandom(); + const { a, aForHash, u } = await generateAndCheckRandom(); const gB = bigIntMod(B.subtract(kgX), p); if (!isGoodModExpFirst(gB, p)) { throw new Error('bad gB'); @@ -267,15 +242,10 @@ async function computeCheck(request, password) { K, ])); - return new constructors.InputCheckPasswordSRP({ - srpId: request.srpId, + return new Api.InputCheckPasswordSRP({ + srpId, A: Buffer.from(aForHash), M1, }); } - -module.exports = { - computeCheck, - computeDigest, -}; diff --git a/src/lib/gramjs/Utils.js b/src/lib/gramjs/Utils.js deleted file mode 100644 index fc5dd9b0f..000000000 --- a/src/lib/gramjs/Utils.js +++ /dev/null @@ -1,717 +0,0 @@ -const { constructors } = require('./tl'); - -// eslint-disable-next-line max-len -const JPEG_HEADER = Buffer.from('ffd8ffe000104a46494600010100000100010000ffdb004300281c1e231e19282321232d2b28303c64413c37373c7b585d4964918099968f808c8aa0b4e6c3a0aadaad8a8cc8ffcbdaeef5ffffff9bc1fffffffaffe6fdfff8ffdb0043012b2d2d3c353c76414176f8a58ca5f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8ffc00011080000000003012200021101031101ffc4001f0000010501010101010100000000000000000102030405060708090a0bffc400b5100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9faffc4001f0100030101010101010101010000000000000102030405060708090a0bffc400b51100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00', 'hex'); -const JPEG_FOOTER = Buffer.from('ffd9', 'hex'); - -// eslint-disable-next-line @typescript-eslint/naming-convention -function _raiseCastFail(entity, target) { - throw new Error(`Cannot cast ${entity.className} to any kind of ${target}`); -} - -/** - Gets the input peer for the given "entity" (user, chat or channel). - - A ``TypeError`` is raised if the given entity isn't a supported type - or if ``check_hash is True`` but the entity's ``accessHash is None`` - *or* the entity contains ``min`` information. In this case, the hash - cannot be used for general purposes, and thus is not returned to avoid - any issues which can derive from invalid access hashes. - - Note that ``check_hash`` **is ignored** if an input peer is already - passed since in that case we assume the user knows what they're doing. - This is key to getting entities by explicitly passing ``hash = 0``. - - * @param entity - * @param allowSelf - * @param checkHash - */ -function getInputPeer(entity, allowSelf = true, checkHash = true) { - if (entity.SUBCLASS_OF_ID === undefined) { - // e.g. custom.Dialog (can't cyclic import). - - if (allowSelf && 'inputEntity' in entity) { - return entity.inputEntity; - } else if ('entity' in entity) { - return getInputPeer(entity.entity); - } else { - _raiseCastFail(entity, 'InputPeer'); - } - } - if (entity.SUBCLASS_OF_ID === 0xc91c90b6) { // crc32(b'InputPeer') - return entity; - } - - if (entity instanceof constructors.User) { - if (entity.isSelf && allowSelf) { - return new constructors.InputPeerSelf(); - } else if (entity.accessHash !== undefined || !checkHash) { - return new constructors.InputPeerUser({ - userId: entity.id, - accessHash: entity.accessHash, - }); - } else { - throw new Error('User without accessHash or min info cannot be input'); - } - } - if (entity instanceof constructors.Chat || entity instanceof constructors.ChatEmpty - || entity instanceof constructors.ChatForbidden) { - return new constructors.InputPeerChat({ chatId: entity.id }); - } - if (entity instanceof constructors.Channel) { - if (entity.accessHash !== undefined || !checkHash) { - return new constructors.InputPeerChannel({ - channelId: entity.id, - accessHash: entity.accessHash, - }); - } else { - throw new TypeError('Channel without accessHash or min info cannot be input'); - } - } - if (entity instanceof constructors.ChannelForbidden) { - // "channelForbidden are never min", and since their hash is - // also not optional, we assume that this truly is the case. - return new constructors.InputPeerChannel({ - channelId: entity.id, - accessHash: entity.accessHash, - }); - } - - if (entity instanceof constructors.InputUser) { - return new constructors.InputPeerUser({ - userId: entity.userId, - accessHash: entity.accessHash, - }); - } - if (entity instanceof constructors.InputChannel) { - return new constructors.InputPeerChannel({ - channelId: entity.channelId, - accessHash: entity.accessHash, - }); - } - if (entity instanceof constructors.UserEmpty) { - return new constructors.InputPeerEmpty(); - } - if (entity instanceof constructors.UserFull) { - return getInputPeer(entity.user); - } - - if (entity instanceof constructors.ChatFull) { - return new constructors.InputPeerChat({ chatId: entity.id }); - } - - if (entity instanceof constructors.PeerChat) { - return new constructors.InputPeerChat(entity.chatId); - } - - _raiseCastFail(entity, 'InputPeer'); - return undefined; -} - -/** - Similar to :meth:`get_input_peer`, but for :tl:`InputChannel`'s alone. - - .. important:: - - This method does not validate for invalid general-purpose access - hashes, unlike `get_input_peer`. Consider using instead: - ``get_input_channel(get_input_peer(channel))``. - - * @param entity - * @returns {InputChannel|*} - */ -/* CONTEST -function getInputChannel(entity) { - if (entity.SUBCLASS_OF_ID === undefined) { - _raiseCastFail(entity, 'InputChannel') - } - - if (entity.SUBCLASS_OF_ID === 0x40f202fd) { // crc32(b'InputChannel') - return entity - } - if (entity instanceof constructors.Channel || entity instanceof constructors.ChannelForbidden) { - return new constructors.InputChannel({ - channelId: entity.id, - accessHash: entity.accessHash || 0 - }) - } - - if (entity instanceof constructors.InputPeerChannel) { - return new constructors.InputChannel({ - channelId: entity.channelId, - accessHash: entity.accessHash - }) - } - _raiseCastFail(entity, 'InputChannel') -} -*/ -/** - Similar to :meth:`get_input_peer`, but for :tl:`InputUser`'s alone. - - .. important:: - - This method does not validate for invalid general-purpose access - hashes, unlike `get_input_peer`. Consider using instead: - ``get_input_channel(get_input_peer(channel))``. - - * @param entity - */ -/* CONTEST -function getInputUser(entity) { - if (entity.SUBCLASS_OF_ID === undefined) { - _raiseCastFail(entity, 'InputUser') - } - if (entity.SUBCLASS_OF_ID === 0xe669bf46) { // crc32(b'InputUser') - return entity - } - - if (entity instanceof constructors.User) { - if (entity.isSelf) { - return new constructors.InputPeerSelf() - } else { - return new constructors.InputUser({ - userId: entity.id, - accessHash: entity.accessHash || 0, - }) - } - } - if (entity instanceof constructors.InputPeerSelf) { - return new constructors.InputPeerSelf() - } - if (entity instanceof constructors.UserEmpty || entity instanceof constructors.InputPeerEmpty) { - return new constructors.InputUserEmpty() - } - - if (entity instanceof constructors.UserFull) { - return getInputUser(entity.user) - } - - if (entity instanceof constructors.InputPeerUser) { - return new constructors.InputUser({ - userId: entity.userId, - accessHash: entity.accessHash - }) - } - - _raiseCastFail(entity, 'InputUser') -} -*/ -/** - Similar to :meth:`get_input_peer`, but for dialogs - * @param dialog - */ -/* CONTEST -function getInputDialog(dialog) { - try { - if (dialog.SUBCLASS_OF_ID === 0xa21c9795) { // crc32(b'InputDialogPeer') - return dialog - } - if (dialog.SUBCLASS_OF_ID === 0xc91c90b6) { // crc32(b'InputPeer') - return new constructors.InputDialogPeer({ peer: dialog }) - } - } catch (e) { - _raiseCastFail(dialog, 'InputDialogPeer') - } - - try { - return new constructors.InputDialogPeer(getInputPeer(dialog)) - // eslint-disable-next-line no-empty - } catch (e) { - - } - _raiseCastFail(dialog, 'InputDialogPeer') -} -*/ - -/* CONTEST - -function getInputMessage(message) { - try { - if (typeof message == 'number') { // This case is really common too - return new constructors.InputMessageID({ - id: message, - }) - } else if (message.SUBCLASS_OF_ID === 0x54b6bcc5) { // crc32(b'InputMessage') - return message - } else if (message.SUBCLASS_OF_ID === 0x790009e3) { // crc32(b'Message') - return new constructors.InputMessageID(message.id) - } - // eslint-disable-next-line no-empty - } catch (e) { - } - - _raiseCastFail(message, 'InputMessage') -} -*/ - -/** - * Adds the JPG header and footer to a stripped image. - * Ported from https://github.com/telegramdesktop/ - * tdesktop/blob/bec39d89e19670eb436dc794a8f20b657cb87c71/Telegram/SourceFiles/ui/image/image.cpp#L225 - - * @param stripped{Buffer} - * @returns {Buffer} - */ -function strippedPhotoToJpg(stripped) { - // Note: Changes here should update _stripped_real_length - if (stripped.length < 3 || stripped[0] !== 1) { - return stripped; - } - const header = Buffer.from(JPEG_HEADER); - // eslint-disable-next-line prefer-destructuring - header[164] = stripped[1]; - // eslint-disable-next-line prefer-destructuring - header[166] = stripped[2]; - return Buffer.concat([header, stripped.slice(3), JPEG_FOOTER]); -} - -/* CONTEST -function getInputLocation(location) { - try { - if (!location.SUBCLASS_OF_ID) { - throw new Error() - } - if (location.SUBCLASS_OF_ID === 0x1523d462) { - return { - dcId: null, - inputLocation: location - } - } - } catch (e) { - _raiseCastFail(location, 'InputFileLocation') - } - if (location instanceof constructors.Message) { - location = location.media - } - - if (location instanceof constructors.MessageMediaDocument) { - location = location.document - } else if (location instanceof constructors.MessageMediaPhoto) { - location = location.photo - } - - if (location instanceof constructors.Document) { - return { - dcId: location.dcId, - inputLocation: new constructors.InputDocumentFileLocation({ - id: location.id, - accessHash: location.accessHash, - fileReference: location.fileReference, - thumbSize: '', // Presumably to download one of its thumbnails - }), - } - } else if (location instanceof constructors.Photo) { - return { - dcId: location.dcId, - inputLocation: new constructors.InputPhotoFileLocation({ - id: location.id, - accessHash: location.accessHash, - fileReference: location.fileReference, - thumbSize: location.sizes[location.sizes.length - 1].type, - }), - } - } - - if (location instanceof constructors.FileLocationToBeDeprecated) { - throw new Error('Unavailable location cannot be used as input') - } - _raiseCastFail(location, 'InputFileLocation') -} -*/ - -/** - * Gets the appropriated part size when downloading files, - * given an initial file size. - * @param fileSize - * @returns {Number} - */ -function getDownloadPartSize(fileSize) { - if (fileSize <= 65536) { // 64KB - return 64; - } - if (fileSize <= 104857600) { // 100MB - return 128; - } - if (fileSize <= 786432000) { // 750MB - return 256; - } - if (fileSize <= 2097152000) { // 2000MB - return 512; - } - if (fileSize <= 4194304000) { // 4000MB - return 1024; - } - - throw new Error('File size too large'); -} - -/** - * Gets the appropriated part size when uploading files, - * given an initial file size. - * @param fileSize - * @returns {Number} - */ -function getUploadPartSize(fileSize) { - if (fileSize <= 104857600) { // 100MB - return 128; - } - if (fileSize <= 786432000) { // 750MB - return 256; - } - if (fileSize <= 2097152000) { // 2000MB - return 512; - } - if (fileSize <= 4194304000) { // 4000MB - return 512; - } - - throw new Error('File size too large'); -} - -/* CONTEST -function getPeer(peer) { - try { - if (typeof peer === 'number') { - const res = resolveId(peer) - - if (res[1] === constructors.PeerChannel) { - return new res[1]({ channelId: res[0] }) - } else if (res[1] === constructors.PeerChat) { - return new res[1]({ chatId: res[0] }) - } else { - return new res[1]({ userId: res[0] }) - } - } - if (peer.SUBCLASS_OF_ID === undefined) { - throw new Error() - } - if (peer.SUBCLASS_OF_ID === 0x2d45687) { - return peer - } else if (peer instanceof constructors.contacts.ResolvedPeer || - peer instanceof constructors.InputNotifyPeer || peer instanceof constructors.TopPeer || - peer instanceof constructors.Dialog || peer instanceof constructors.DialogPeer) { - return peer.peer - } else if (peer instanceof constructors.ChannelFull) { - return new constructors.PeerChannel({ channelId: peer.id }) - } - if (peer.SUBCLASS_OF_ID === 0x7d7c6f86 || peer.SUBCLASS_OF_ID === 0xd9c7fc18) { - // ChatParticipant, ChannelParticipant - return new constructors.PeerUser({ userId: peer.userId }) - } - peer = getInputPeer(peer, false, false) - - if (peer instanceof constructors.InputPeerUser) { - return new constructors.PeerUser({ userId: peer.userId }) - } else if (peer instanceof constructors.InputPeerChat) { - return new constructors.PeerChat({ chatId: peer.chatId }) - } else if (peer instanceof constructors.InputPeerChannel) { - return new constructors.PeerChannel({ channelId: peer.channelId }) - } - // eslint-disable-next-line no-empty - } catch (e) { - console.log(e) - } - _raiseCastFail(peer, 'peer') -} -*/ - -/** - Convert the given peer into its marked ID by default. - - This "mark" comes from the "bot api" format, and with it the peer type - can be identified back. User ID is left unmodified, chat ID is negated, - and channel ID is prefixed with -100: - - * ``userId`` - * ``-chatId`` - * ``-100channel_id`` - - The original ID and the peer type class can be returned with - a call to :meth:`resolve_id(marked_id)`. - * @param peer - * @param addMark - */ -/* CONTEST -function getPeerId(peer, addMark = true) { - // First we assert it's a Peer TLObject, or early return for integers - if (typeof peer == 'number') { - return addMark ? peer : resolveId(peer)[0] - } - - // Tell the user to use their client to resolve InputPeerSelf if we got one - if (peer instanceof constructors.InputPeerSelf) { - _raiseCastFail(peer, 'int (you might want to use client.get_peer_id)') - } - - try { - peer = getPeer(peer) - } catch (e) { - _raiseCastFail(peer, 'int') - } - if (peer instanceof constructors.PeerUser) { - return peer.userId - } else if (peer instanceof constructors.PeerChat) { - // Check in case the user mixed things up to avoid blowing up - if (!(0 < peer.chatId <= 0x7fffffff)) { - peer.chatId = resolveId(peer.chatId)[0] - } - - return addMark ? -(peer.chatId) : peer.chatId - } else { // if (peer instanceof constructors.PeerChannel) - // Check in case the user mixed things up to avoid blowing up - if (!(0 < peer.channelId <= 0x7fffffff)) { - peer.channelId = resolveId(peer.channelId)[0] - } - if (!addMark) { - return peer.channelId - } - // Concat -100 through math tricks, .to_supergroup() on - // Madeline IDs will be strictly positive -> log works. - try { - return -(peer.channelId + Math.pow(10, Math.floor(Math.log10(peer.channelId) + 3))) - } catch (e) { - throw new Error('Cannot get marked ID of a channel unless its ID is strictly positive') - } - } -} -*/ -/** - * Given a marked ID, returns the original ID and its :tl:`Peer` type. - * @param markedId - */ -/* CONTEST -function resolveId(markedId) { - if (markedId >= 0) { - return [markedId, constructors.PeerUser] - } - - // There have been report of chat IDs being 10000xyz, which means their - // marked version is -10000xyz, which in turn looks like a channel but - // it becomes 00xyz (= xyz). Hence, we must assert that there are only - // two zeroes. - const m = markedId.toString() - .match(/-100([^0]\d*)/) - if (m) { - return [parseInt(m[1]), constructors.PeerChannel] - } - return [-markedId, constructors.PeerChat] -} -*/ - -/** - * returns an entity pair - * @param entityId - * @param entities - * @param cache - * @param getInputPeer - * @returns {{inputEntity: *, entity: *}} - * @private - */ - -/* CONTEST - -function _getEntityPair(entityId, entities, cache, getInputPeer = getInputPeer) { - const entity = entities.get(entityId) - let inputEntity = cache[entityId] - if (inputEntity === undefined) { - try { - inputEntity = getInputPeer(inputEntity) - } catch (e) { - inputEntity = null - } - } - return { - entity, - inputEntity - } -} -*/ - -function getMessageId(message) { - if (message === undefined) { - return undefined; - } - if (typeof message === 'number') { - return message; - } - if (message.SUBCLASS_OF_ID === 0x790009e3) { // crc32(b'Message') - return message.id; - } - throw new Error(`Invalid message type: ${message.constructor.name}`); -} - -/** - Parses the given username or channel access hash, given - a string, username or URL. Returns a tuple consisting of - both the stripped, lowercase username and whether it is - a joinchat/ hash (in which case is not lowercase'd). - - Returns ``(None, False)`` if the ``username`` or link is not valid. - - * @param username {string} - */ - -/* CONTEST - -function parseUsername(username) { - username = username.trim() - const m = username.match(USERNAME_RE) || username.match(TG_JOIN_RE) - if (m) { - username = username.replace(m[0], '') - if (m[1]) { - return { - username: username, - isInvite: true - } - } else { - username = rtrim(username, '/') - } - } - if (username.match(VALID_USERNAME_RE)) { - return { - username: username.toLowerCase(), - isInvite: false - } - } else { - return { - username: null, - isInvite: false - } - } -} - -function rtrim(s, mask) { - while (~mask.indexOf(s[s.length - 1])) { - s = s.slice(0, -1) - } - return s -} - - */ - -/** - * Gets the display name for the given :tl:`User`, - :tl:`Chat` or :tl:`Channel`. Returns an empty string otherwise - * @param entity - */ -function getDisplayName(entity) { - if (entity instanceof constructors.User) { - if (entity.lastName && entity.firstName) { - return `${entity.firstName} ${entity.lastName}`; - } else if (entity.firstName) { - return entity.firstName; - } else if (entity.lastName) { - return entity.lastName; - } else { - return ''; - } - } else if (entity instanceof constructors.Chat || entity instanceof constructors.Channel) { - return entity.title; - } - return ''; -} - -/** - * check if a given item is an array like or not - * @param item - * @returns {boolean} - */ - -/* CONTEST -Duplicate ? -function isListLike(item) { - return ( - Array.isArray(item) || - (Boolean(item) && - typeof item === 'object' && - typeof (item.length) === 'number' && - (item.length === 0 || - (item.length > 0 && - (item.length - 1) in item) - ) - ) - ) -} -*/ -/** - * Returns the appropriate DC based on the id - * @param dcId the id of the DC. - * @param downloadDC whether to use -1 DCs or not - * (These only support downloading/uploading and not creating a new AUTH key) - * @return {{port: number, ipAddress: string, id: number}} - */ -function getDC(dcId, downloadDC = false) { - // TODO Move to external config - switch (dcId) { - case 1: - return { - id: 1, - ipAddress: `zws1${downloadDC ? '-1' : ''}.web.telegram.org`, - port: 443, - }; - case 2: - return { - id: 2, - ipAddress: `zws2${downloadDC ? '-1' : ''}.web.telegram.org`, - port: 443, - }; - case 3: - return { - id: 3, - ipAddress: `zws3${downloadDC ? '-1' : ''}.web.telegram.org`, - port: 443, - }; - case 4: - return { - id: 4, - ipAddress: `zws4${downloadDC ? '-1' : ''}.web.telegram.org`, - port: 443, - }; - case 5: - return { - id: 5, - ipAddress: `zws5${downloadDC ? '-1' : ''}.web.telegram.org`, - port: 443, - }; - default: - throw new Error(`Cannot find the DC with the ID of ${dcId}`); - } - // TODO chose based on current connection method - /* - if (!this._config) { - this._config = await this.invoke(new requests.help.GetConfig()) - } - if (cdn && !this._cdnConfig) { - this._cdnConfig = await this.invoke(new requests.help.GetCdnConfig()) - for (const pk of this._cdnConfig.publicKeys) { - addKey(pk.publicKey) - } - } - for (const DC of this._config.dcOptions) { - if (DC.id === dcId && Boolean(DC.ipv6) === this._useIPV6 && Boolean(DC.cdn) === cdn) { - return DC - } - } */ -} - -module.exports = { - getMessageId, - // _getEntityPair, - // getInputMessage, - // getInputDialog, - // getInputUser, - // getInputChannel, - getInputPeer, - // parsePhone, - // parseUsername, - // getPeer, - // getPeerId, - getDisplayName, - // resolveId, - // isListLike, - getDownloadPartSize, - getUploadPartSize, - // getInputLocation, - strippedPhotoToJpg, - getDC, -}; diff --git a/src/lib/gramjs/Utils.ts b/src/lib/gramjs/Utils.ts new file mode 100644 index 000000000..fd01eef81 --- /dev/null +++ b/src/lib/gramjs/Utils.ts @@ -0,0 +1,253 @@ +import type { Entity, EntityLike } from './types'; + +import { Api } from './tl'; + +// eslint-disable-next-line max-len +const JPEG_HEADER = Buffer.from('ffd8ffe000104a46494600010100000100010000ffdb004300281c1e231e19282321232d2b28303c64413c37373c7b585d4964918099968f808c8aa0b4e6c3a0aadaad8a8cc8ffcbdaeef5ffffff9bc1fffffffaffe6fdfff8ffdb0043012b2d2d3c353c76414176f8a58ca5f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8ffc00011080000000003012200021101031101ffc4001f0000010501010101010100000000000000000102030405060708090a0bffc400b5100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9faffc4001f0100030101010101010101010000000000000102030405060708090a0bffc400b51100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00', 'hex'); +const JPEG_FOOTER = Buffer.from('ffd9', 'hex'); + +// eslint-disable-next-line @typescript-eslint/naming-convention +function _raiseCastFail(entity: any, target: string) { + throw new Error(`Cannot cast ${entity.className} to any kind of ${target}`); +} + +/** + Gets the input peer for the given "entity" (user, chat or channel). + + A ``TypeError`` is raised if the given entity isn't a supported type + or if ``check_hash is True`` but the entity's ``accessHash is None`` + *or* the entity contains ``min`` information. In this case, the hash + cannot be used for general purposes, and thus is not returned to avoid + any issues which can derive from invalid access hashes. + + Note that ``check_hash`` **is ignored** if an input peer is already + passed since in that case we assume the user knows what they're doing. + This is key to getting entities by explicitly passing ``hash = 0``. + + * @param entity + * @param allowSelf + * @param checkHash + */ +export function getInputPeer(entity: Entity, allowSelf = true, checkHash = true): Api.TypeInputPeer { + if (entity.SUBCLASS_OF_ID === 0xc91c90b6) { // crc32(b'InputPeer') + return entity; + } + + if (entity instanceof Api.User) { + if (entity.self && allowSelf) { + return new Api.InputPeerSelf(); + } else if (entity.accessHash !== undefined || !checkHash) { + return new Api.InputPeerUser({ + userId: entity.id, + accessHash: entity.accessHash!, + }); + } else { + throw new Error('User without accessHash or min info cannot be input'); + } + } + if (entity instanceof Api.Chat || entity instanceof Api.ChatEmpty + || entity instanceof Api.ChatForbidden) { + return new Api.InputPeerChat({ chatId: entity.id }); + } + if (entity instanceof Api.Channel) { + if (entity.accessHash !== undefined || !checkHash) { + return new Api.InputPeerChannel({ + channelId: entity.id, + accessHash: entity.accessHash!, + }); + } else { + throw new TypeError('Channel without accessHash or min info cannot be input'); + } + } + if (entity instanceof Api.ChannelForbidden) { + // "channelForbidden are never min", and since their hash is + // also not optional, we assume that this truly is the case. + return new Api.InputPeerChannel({ + channelId: entity.id, + accessHash: entity.accessHash, + }); + } + + if (entity instanceof Api.InputUser) { + return new Api.InputPeerUser({ + userId: entity.userId, + accessHash: entity.accessHash, + }); + } + if (entity instanceof Api.InputChannel) { + return new Api.InputPeerChannel({ + channelId: entity.channelId, + accessHash: entity.accessHash, + }); + } + if (entity instanceof Api.UserEmpty) { + return new Api.InputPeerEmpty(); + } + + _raiseCastFail(entity, 'InputPeer'); + return new Api.InputPeerEmpty(); +} + +/** + * Adds the JPG header and footer to a stripped image. + * Ported from https://github.com/telegramdesktop/ + * tdesktop/blob/bec39d89e19670eb436dc794a8f20b657cb87c71/Telegram/SourceFiles/ui/image/image.cpp#L225 + + * @param stripped{Buffer} + * @returns {Buffer} + */ +export function strippedPhotoToJpg(stripped: Buffer) { + // Note: Changes here should update _stripped_real_length + if (stripped.length < 3 || stripped[0] !== 1) { + return stripped; + } + const header = Buffer.from(JPEG_HEADER); + header[164] = stripped[1]; + header[166] = stripped[2]; + return Buffer.concat([header, stripped.slice(3), JPEG_FOOTER]); +} + +/** + * Gets the appropriated part size when downloading files, + * given an initial file size. + * @param fileSize + * @returns {Number} + */ +export function getDownloadPartSize(fileSize: number) { + if (fileSize <= 65536) { // 64KB + return 64; + } + if (fileSize <= 104857600) { // 100MB + return 128; + } + if (fileSize <= 786432000) { // 750MB + return 256; + } + if (fileSize <= 2097152000) { // 2000MB + return 512; + } + if (fileSize <= 4194304000) { // 4000MB + return 1024; + } + + throw new Error('File size too large'); +} + +/** + * Gets the appropriated part size when uploading files, + * given an initial file size. + * @param fileSize + * @returns {Number} + */ +export function getUploadPartSize(fileSize: number) { + if (fileSize <= 104857600) { // 100MB + return 128; + } + if (fileSize <= 786432000) { // 750MB + return 256; + } + if (fileSize <= 2097152000) { // 2000MB + return 512; + } + if (fileSize <= 4194304000) { // 4000MB + return 512; + } + + throw new Error('File size too large'); +} + +export function getMessageId(message: number | Api.TypeMessage) { + if (message === undefined) { + return undefined; + } + if (typeof message === 'number') { + return message; + } + if (message.SUBCLASS_OF_ID === 0x790009e3) { // crc32(b'Message') + return message.id; + } + throw new Error(`Invalid message type: ${message.constructor.name}`); +} + +/** + * Gets the display name for the given :tl:`User`, + :tl:`Chat` or :tl:`Channel`. Returns an empty string otherwise + * @param entity + */ +export function getDisplayName(entity: Entity) { + if (entity instanceof Api.User) { + if (entity.lastName && entity.firstName) { + return `${entity.firstName} ${entity.lastName}`; + } else if (entity.firstName) { + return entity.firstName; + } else if (entity.lastName) { + return entity.lastName; + } else { + return ''; + } + } else if (entity instanceof Api.Chat || entity instanceof Api.Channel) { + return entity.title; + } + return ''; +} + +/** + * Returns the appropriate DC based on the id + * @param dcId the id of the DC. + * @param downloadDC whether to use -1 DCs or not + * (These only support downloading/uploading and not creating a new AUTH key) + * @return {{port: number, ipAddress: string, id: number}} + */ +export function getDC(dcId: number, downloadDC = false) { + // TODO Move to external config + switch (dcId) { + case 1: + return { + id: 1, + ipAddress: `zws1${downloadDC ? '-1' : ''}.web.telegram.org`, + port: 443, + }; + case 2: + return { + id: 2, + ipAddress: `zws2${downloadDC ? '-1' : ''}.web.telegram.org`, + port: 443, + }; + case 3: + return { + id: 3, + ipAddress: `zws3${downloadDC ? '-1' : ''}.web.telegram.org`, + port: 443, + }; + case 4: + return { + id: 4, + ipAddress: `zws4${downloadDC ? '-1' : ''}.web.telegram.org`, + port: 443, + }; + case 5: + return { + id: 5, + ipAddress: `zws5${downloadDC ? '-1' : ''}.web.telegram.org`, + port: 443, + }; + default: + throw new Error(`Cannot find the DC with the ID of ${dcId}`); + } + // TODO chose based on current connection method + /* + if (!this._config) { + this._config = await this.invoke(new requests.help.GetConfig()) + } + if (cdn && !this._cdnConfig) { + this._cdnConfig = await this.invoke(new requests.help.GetCdnConfig()) + for (const pk of this._cdnConfig.publicKeys) { + addKey(pk.publicKey) + } + } + for (const DC of this._config.dcOptions) { + if (DC.id === dcId && Boolean(DC.ipv6) === this._useIPV6 && Boolean(DC.cdn) === cdn) { + return DC + } + } */ +} diff --git a/src/lib/gramjs/Version.js b/src/lib/gramjs/Version.js deleted file mode 100644 index 092443805..000000000 --- a/src/lib/gramjs/Version.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = '0.0.2'; diff --git a/src/lib/gramjs/client/2fa.ts b/src/lib/gramjs/client/2fa.ts index 64f7faefe..3909335f8 100644 --- a/src/lib/gramjs/client/2fa.ts +++ b/src/lib/gramjs/client/2fa.ts @@ -1,8 +1,7 @@ import type TelegramClient from './TelegramClient'; -import errors from '../errors'; -// eslint-disable-next-line import/no-named-default -import { default as Api } from '../tl/api'; +import { EmailUnconfirmedError, PasswordModifiedError, RPCError } from '../errors'; +import Api from '../tl/api'; import { generateRandomBytes } from '../Helpers'; import { computeCheck, computeDigest } from '../Password'; @@ -23,7 +22,7 @@ export interface TwoFaPasswordParams { } export type TmpPasswordResult = Api.account.TmpPassword | { error: string } | undefined; -export type PasswordResult = Api.account.Password | { error: string } | undefined; +export type PasswordResult = Api.TypeInputCheckPasswordSRP | { error: string } | undefined; /** * Changes the 2FA settings of the logged in user. @@ -83,9 +82,13 @@ export async function updateTwoFaSettings( const pwd = await client.invoke(new Api.account.GetPassword()); - if (!(pwd.newAlgo instanceof Api.PasswordKdfAlgoUnknown)) { - pwd.newAlgo.salt1 = Buffer.concat([pwd.newAlgo.salt1, generateRandomBytes(32)]); + const newAlgo = pwd.newAlgo; + + if (newAlgo instanceof Api.PasswordKdfAlgoUnknown) { + throw new Error('Password algorithm is unknown'); } + + newAlgo.salt1 = Buffer.concat([newAlgo.salt1, generateRandomBytes(32)]); if (!pwd.hasPassword && currentPassword) { currentPassword = undefined; } @@ -101,8 +104,8 @@ export async function updateTwoFaSettings( await client.invoke(new Api.account.UpdatePasswordSettings({ password, newSettings: new Api.account.PasswordInputSettings({ - newAlgo: pwd.newAlgo, - newPasswordHash: newPassword ? await computeDigest(pwd.newAlgo, newPassword) : Buffer.alloc(0), + newAlgo, + newPasswordHash: newPassword ? await computeDigest(newAlgo, newPassword) : Buffer.alloc(0), hint, email, // not explained what it does and it seems to always be set to empty in tdesktop @@ -110,7 +113,7 @@ export async function updateTwoFaSettings( }), })); } catch (e) { - if (e instanceof errors.EmailUnconfirmedError) { + if (e instanceof EmailUnconfirmedError) { // eslint-disable-next-line no-constant-condition while (true) { try { @@ -147,9 +150,9 @@ export async function getTmpPassword(client: TelegramClient, currentPassword: st })); return result; - } catch (err: any) { - if (err.message === 'PASSWORD_HASH_INVALID') { - return { error: err.message }; + } catch (err: unknown) { + if (err instanceof RPCError && err.errorMessage === 'PASSWORD_HASH_INVALID') { + return { error: err.errorMessage }; } throw err; @@ -162,7 +165,7 @@ export async function getCurrentPassword( currentPassword, onPasswordCodeError, }: TwoFaPasswordParams, -) { +): Promise { const pwd = await client.invoke(new Api.account.GetPassword()); if (!pwd) { @@ -172,10 +175,11 @@ export async function getCurrentPassword( try { return currentPassword ? await computeCheck(pwd, currentPassword!) : new Api.InputCheckPasswordEmpty(); } catch (err: any) { - if (err instanceof errors.PasswordModifiedError) { - return onPasswordCodeError!(err); - } else if (err.message === 'PASSWORD_HASH_INVALID') { - return { error: err.message }; + if (err instanceof PasswordModifiedError) { + onPasswordCodeError!(err); + return undefined; + } else if (err instanceof RPCError && err.errorMessage ==='PASSWORD_HASH_INVALID') { + return { error: err.errorMessage }; } else { throw err; } diff --git a/src/lib/gramjs/client/MockClient.ts b/src/lib/gramjs/client/MockClient.ts index 0623e3141..ce0f2551c 100644 --- a/src/lib/gramjs/client/MockClient.ts +++ b/src/lib/gramjs/client/MockClient.ts @@ -1,7 +1,8 @@ import BigInt from 'big-integer'; -import type { DownloadFileParams } from './downloadFile'; +import type { DownloadFileWithDcParams } from './downloadFile'; import type { MockTypes } from './mockUtils/MockTypes'; +import type { SizeType } from './TelegramClient'; import { GENERAL_TOPIC_ID } from '../../../config'; import { UpdateConnectionState } from '../network'; @@ -22,7 +23,7 @@ import { downloadFile } from './downloadFile'; import MockSender from './MockSender'; -const sizeTypes = ['u', 'v', 'w', 'y', 'd', 'x', 'c', 'm', 'b', 'a', 's', 'f']; +const sizeTypes: SizeType[] = ['u', 'v', 'w', 'y', 'd', 'x', 'c', 'm', 'b', 'a', 's', 'f']; class TelegramClient { private invokeMiddleware?: (mockClient: TelegramClient, request: Api.Request) @@ -282,7 +283,7 @@ class TelegramClient { return new MockSender(this); } - downloadFile(inputLocation: any, args: DownloadFileParams) { + downloadFile(inputLocation: any, args: DownloadFileWithDcParams) { return downloadFile(this as any, inputLocation, args); } diff --git a/src/lib/gramjs/client/TelegramClient.d.ts b/src/lib/gramjs/client/TelegramClient.d.ts deleted file mode 100644 index 42486cc18..000000000 --- a/src/lib/gramjs/client/TelegramClient.d.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { - PasswordResult, TmpPasswordResult, TwoFaParams, TwoFaPasswordParams, updateTwoFaSettings, -} from './2fa'; -import type { BotAuthParams, UserAuthParams } from './auth'; -import type { downloadFile, DownloadFileParams } from './downloadFile'; -import type { uploadFile, UploadFileParams } from './uploadFile'; - -import type { Api } from '..'; - -declare class TelegramClient { - constructor(...args: any); - - async start(authParams: UserAuthParams | BotAuthParams); - - async invoke( - request: R, dcId?: number, abortSignal?: AbortSignal, shouldRetryOnTimeout?: boolean, - ): Promise; - - async invokeBeacon(request: R, dcId?: number): void; - - async uploadFile(uploadParams: UploadFileParams): ReturnType; - - async downloadFile(uploadParams: DownloadFileParams): ReturnType; - - async updateTwoFaSettings(Params: TwoFaParams): ReturnType; - - async getTmpPassword(currentPassword: string, ttl?: number): Promise; - - async getCurrentPassword(Params: TwoFaPasswordParams): Promise; - - setPingCallback(callback: () => Promise); - - setForceHttpTransport: (forceHttpTransport: boolean) => void; - - setAllowHttpTransport: (allowHttpTransport: boolean) => void; - - // Untyped methods. - [prop: string]: any; -} - -export default TelegramClient; diff --git a/src/lib/gramjs/client/TelegramClient.js b/src/lib/gramjs/client/TelegramClient.ts similarity index 58% rename from src/lib/gramjs/client/TelegramClient.js rename to src/lib/gramjs/client/TelegramClient.ts index 45d95f14d..075515e22 100644 --- a/src/lib/gramjs/client/TelegramClient.js +++ b/src/lib/gramjs/client/TelegramClient.ts @@ -1,35 +1,87 @@ -const os = require('os'); -const Logger = require('../extensions/Logger'); -const { sleep } = require('../Helpers'); -const errors = require('../errors'); -const MemorySession = require('../sessions/Memory'); -const Helpers = require('../Helpers'); -const utils = require('../Utils'); -const Session = require('../sessions/Abstract'); -const { LAYER } = require('../tl/AllTLObjects'); -const { - constructors, - requests, -} = require('../tl'); -const { +import os from 'os'; +import bigInt from 'big-integer'; +import { Logger } from '../extensions'; +import { getRandomInt, sleep } from '../Helpers'; +import MemorySession from '../sessions/Memory'; +import Session from '../sessions/Abstract'; +import { LAYER } from '../tl/AllTLObjects'; +import { Api } from '../tl'; +import { ConnectionTCPObfuscated, MTProtoSender, UpdateConnectionState, HttpConnection, -} = require('../network'); -const { - authFlow, - checkAuthorization, -} = require('./auth'); -const { downloadFile } = require('./downloadFile'); -const { uploadFile } = require('./uploadFile'); -const { + Connection, + UpdateServerTimeOffset, +} from '../network'; +import { UserAuthParams, authFlow, checkAuthorization } from './auth'; +import { DownloadFileParams, DownloadFileWithDcParams, DownloadMediaParams, downloadFile } from './downloadFile'; +import { UploadFileParams, uploadFile } from './uploadFile'; +import { updateTwoFaSettings, getTmpPassword, getCurrentPassword, -} = require('./2fa'); -const RequestState = require('../network/RequestState'); -const Deferred = require('../../../util/Deferred').default; + TwoFaParams, + TmpPasswordResult, + PasswordResult, + TwoFaPasswordParams, +} from './2fa'; +import RequestState from '../network/RequestState'; +import Deferred from '../../../util/Deferred'; +import { getDC, getInputPeer, strippedPhotoToJpg } from '../Utils'; +import { AuthKey } from '../crypto/AuthKey'; +import { + FloodTestPhoneWaitError, + FloodWaitError, + MsgWaitError, + NetworkMigrateError, + PhoneMigrateError, + RPCError, + ServerError, + TimedOutError, + UserMigrateError, +} from '../errors'; +import { UpdatePts } from '../../../api/gramjs/updates/UpdatePts'; +import LocalUpdatePremiumFloodWait from '../../../api/gramjs/updates/UpdatePremiumFloodWait'; + +type TelegramClientParams = { + connection: typeof Connection; + fallbackConnection: typeof Connection; + useIPV6: boolean; + timeout: number; + requestRetries: number; + connectionRetries: number; + connectionRetriesToFallback: number; + retryDelay: number; + retryMainConnectionDelay: number; + autoReconnect: boolean; + sequentialUpdates: boolean; + floodSleepLimit: number; + deviceModel: string; + systemVersion: string; + appVersion: string; + langCode: string; + langPack: string; + systemLangCode: string; + baseLogger: string | Logger; + useWSS: boolean; + additionalDcsDisabled: boolean; + dcId: number; + isTestServerRequested: boolean; + shouldAllowHttpTransport: boolean; + shouldForceHttpTransport: boolean; + shouldDebugExportedSenders: boolean; +}; + +type TimeoutId = ReturnType; + +export type Update = ( + Api.TypeUpdate | Api.TypeUpdates + | UpdateServerTimeOffset | UpdateConnectionState | UpdatePts | LocalUpdatePremiumFloodWait +) & { _entities?: (Api.TypeUser | Api.TypeChat)[] }; +type EventBuilder = { + build: (update: Update) => Update; +} const DEFAULT_DC_ID = 2; const DEFAULT_WEBDOCUMENT_DC_ID = 4; @@ -52,14 +104,14 @@ const PING_WAKE_UP_WARNING_TIMEOUT = 1000; // 1 sec const PING_DISCONNECT_DELAY = 60000; // 1 min // All types -const sizeTypes = ['u', 'v', 'w', 'y', 'd', 'x', 'c', 'm', 'b', 'a', 's', 'f']; +const sizeTypes = ['u', 'v', 'w', 'y', 'd', 'x', 'c', 'm', 'b', 'a', 's', 'f'] as const; +export type SizeType = typeof sizeTypes[number]; class TelegramClient { - static DEFAULT_OPTIONS = { + static DEFAULT_OPTIONS: Partial = { connection: ConnectionTCPObfuscated, fallbackConnection: HttpConnection, useIPV6: false, - proxy: undefined, timeout: 10, requestRetries: 5, connectionRetries: Infinity, @@ -85,18 +137,77 @@ class TelegramClient { shouldDebugExportedSenders: false, }; - /** - * - * @param session {StringSession|LocalStorageSession} - * @param apiId - * @param apiHash - * @param opts - */ - constructor(session, apiId, apiHash, opts = TelegramClient.DEFAULT_OPTIONS) { - if (!apiId || !apiHash) { + private _args: TelegramClientParams; + + public session: Session; + + public apiHash: string; + + public apiId: number; + + public defaultDcId: number; + + private _useIPV6: boolean; + + private _shouldForceHttpTransport: boolean; + + private _shouldAllowHttpTransport: boolean; + + private _shouldDebugExportedSenders: boolean; + + _log: Logger; + + private floodSleepLimit: number; + + private _connection: typeof Connection; + + private _fallbackConnection: typeof Connection; + + private _sender?: MTProtoSender; + + private _eventBuilders: [EventBuilder, CallableFunction][]; + + private _requestRetries: number; + + private _connectionRetries: number; + + private _connectionRetriesToFallback: number; + + private _retryDelay: number; + + private _retryMainConnectionDelay: number; + + private _timeout: number; + + private _autoReconnect: boolean; + + private _config?: Api.Config; + + private _exportedSenderPromises: Record | undefined>> = {}; + private _exportedSenderRefCounter: Record> = {}; + private _waitingForAuthKey: Record | undefined> = {}; + private _exportedSenderReleaseTimeouts: Record> = {}; + private _loopStarted = false; + private _isSwitchingDc = false; + private _destroyed = false; + private _connectedDeferred = new Deferred(); + private pingCallback?: () => Promise; + + private _initWith: (x: unknown) => Api.InvokeWithLayer; + + isPremium = false; + private _lastRequest = Date.now(); + + constructor( + session: Session, + apiId?: number, + apiHash?: string, + opts: Partial = TelegramClient.DEFAULT_OPTIONS, + ) { + if (!apiId || !apiHash || !Number.isFinite(apiId)) { throw Error('Your API ID or Hash are invalid. Please read "Requirements" on README.md'); } - const args = { ...TelegramClient.DEFAULT_OPTIONS, ...opts }; + const args = { ...TelegramClient.DEFAULT_OPTIONS, ...opts } as TelegramClientParams; this.apiId = apiId; this.apiHash = apiHash; this.defaultDcId = args.dcId || DEFAULT_DC_ID; @@ -114,31 +225,23 @@ class TelegramClient { if (typeof session === 'string' || !session) { try { throw new Error('not implemented'); - } catch (e) { + } catch (e: unknown) { session = new MemorySession(); } } else if (!(session instanceof Session)) { throw new Error('The given session must be str or a session instance'); } + this.session = session; this.floodSleepLimit = args.floodSleepLimit; this._eventBuilders = []; - this._phoneCodeHash = {}; - this.session = session; - // this._entityCache = EntityCache(); - this.apiId = parseInt(apiId, 10); - this.apiHash = apiHash; - this._requestRetries = args.requestRetries; this._connectionRetries = args.connectionRetries; this._connectionRetriesToFallback = args.connectionRetriesToFallback; this._retryDelay = args.retryDelay || 0; this._retryMainConnectionDelay = args.retryMainConnectionDelay || 0; - if (args.proxy) { - this._log.warn('proxies are not supported'); - } - this._proxy = args.proxy; + this._timeout = args.timeout; this._autoReconnect = args.autoReconnect; @@ -146,12 +249,10 @@ class TelegramClient { this._fallbackConnection = args.fallbackConnection; // TODO add proxy support - this._floodWaitedRequests = {}; - - this._initWith = (x) => { - return new requests.InvokeWithLayer({ + this._initWith = (x: unknown) => { + return new Api.InvokeWithLayer({ layer: LAYER, - query: new requests.InitConnection({ + query: new Api.InitConnection({ apiId: this.apiId, deviceModel: args.deviceModel || os.type() .toString() || 'Unknown', @@ -168,18 +269,6 @@ class TelegramClient { }; this._args = args; - // These will be set later - this._config = undefined; - this.phoneCodeHashes = []; - this._exportedSenderPromises = {}; - this._exportedSenderRefCounter = {}; - this._waitingForAuthKey = {}; - this._exportedSenderReleaseTimeouts = {}; - this._additionalDcsDisabled = args.additionalDcsDisabled; - this._loopStarted = false; - this._isSwitchingDc = false; - this._destroyed = false; - this._connectedDeferred = new Deferred(); } // region Connecting @@ -212,20 +301,23 @@ class TelegramClient { isMainSender: true, }); } - // set defaults vars - this._sender.userDisconnected = false; - this._sender._user_connected = false; - this._sender.isReconnecting = false; - this._sender._disconnected = true; - const connection = new this._connection( - this.session.serverAddress, this.session.port, this.session.dcId, this._log, this.session.isTestServer, - ); - const fallbackConnection = new this._fallbackConnection( - this.session.serverAddress, this.session.port, this.session.dcId, this._log, this.session.isTestServer, - ); + const connection = new this._connection({ + ip: this.session.serverAddress, + port: this.session.port, + dcId: this.session.dcId, + loggers: this._log, + isTestServer: this.session.isTestServer, + }); + const fallbackConnection = new this._fallbackConnection({ + ip: this.session.serverAddress, + port: this.session.port, + dcId: this.session.dcId, + loggers: this._log, + isTestServer: this.session.isTestServer, + }); - const newConnection = await this._sender.connect(connection, undefined, fallbackConnection); + const newConnection = await this._sender.connect(connection, false, fallbackConnection); if (!newConnection) { // we're already connected so no need to reset auth key. if (!this._loopStarted) { @@ -237,7 +329,7 @@ class TelegramClient { this.session.setAuthKey(this._sender.authKey); await this._sender.send(this._initWith( - new requests.help.GetConfig({}), + new Api.help.GetConfig(), )); if (!this._loopStarted) { @@ -256,7 +348,7 @@ class TelegramClient { await this.session.load(); if (!this.session.serverAddress || (this.session.serverAddress.includes(':') !== this._useIPV6)) { - const DC = utils.getDC(this.defaultDcId); + const DC = getDC(this.defaultDcId); // TODO Fill IP addresses for when `this._useIPV6` is used this.session.setDC( this.defaultDcId, DC.ipAddress, this._args.useWSS ? 443 : 80, this._args.isTestServerRequested, @@ -264,25 +356,25 @@ class TelegramClient { } } - setPingCallback(callback) { + setPingCallback(callback: () => Promise) { this.pingCallback = callback; } - async setForceHttpTransport(forceHttpTransport) { + async setForceHttpTransport(forceHttpTransport: boolean) { this._shouldForceHttpTransport = forceHttpTransport; await this.disconnect(); this._sender = undefined; await this.connect(); } - async setAllowHttpTransport(allowHttpTransport) { + async setAllowHttpTransport(allowHttpTransport: boolean) { this._shouldAllowHttpTransport = allowHttpTransport; await this.disconnect(); this._sender = undefined; await this.connect(); } - setShouldDebugExportedSenders(shouldDebugExportedSenders) { + setShouldDebugExportedSenders(shouldDebugExportedSenders: boolean) { this._shouldDebugExportedSenders = shouldDebugExportedSenders; } @@ -293,9 +385,14 @@ class TelegramClient { async _updateLoop() { let lastPongAt; + const sender = this._sender; + if (!sender) { + throw new Error('Sender is not initialized'); + } + while (!this._destroyed) { - await Helpers.sleep(PING_INTERVAL); - if (this._sender.isReconnecting || this._isSwitchingDc) { + await sleep(PING_INTERVAL); + if (sender.isReconnecting || this._isSwitchingDc) { lastPongAt = undefined; continue; } @@ -305,8 +402,8 @@ class TelegramClient { if (this._destroyed) { return undefined; } - return this._sender.send(new requests.PingDelayDisconnect({ - pingId: Helpers.getRandomInt(Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER), + return sender.send(new Api.PingDelayDisconnect({ + pingId: bigInt(getRandomInt(Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER)), disconnectDelay: PING_DISCONNECT_DELAY, })); }; @@ -317,7 +414,7 @@ class TelegramClient { if (!lastInterval || lastInterval < PING_INTERVAL_TO_WAKE_UP) { await attempts(() => timeout(ping, PING_TIMEOUT), PING_FAIL_ATTEMPTS, PING_FAIL_INTERVAL); } else { - let wakeUpWarningTimeout = setTimeout(() => { + let wakeUpWarningTimeout: TimeoutId | undefined = setTimeout(() => { this._handleUpdate(new UpdateConnectionState(UpdateConnectionState.disconnected)); wakeUpWarningTimeout = undefined; }, PING_WAKE_UP_WARNING_TIMEOUT); @@ -339,13 +436,13 @@ class TelegramClient { lastPongAt = undefined; - if (this._sender.isReconnecting || this._isSwitchingDc) { + if (sender.isReconnecting || this._isSwitchingDc) { continue; } if (this._destroyed) { break; } - this._sender.reconnect(); + sender.reconnect(); } // We need to send some content-related request at least hourly @@ -354,8 +451,8 @@ class TelegramClient { if (Date.now() - this._lastRequest > 30 * 60 * 1000) { try { - await this.pingCallback(); - } catch (e) { + await this.pingCallback?.(); + } catch (e: unknown) { // we don't care about errors here } @@ -370,19 +467,14 @@ class TelegramClient { * @returns {Promise} */ async disconnect() { - if (this._sender) { - await this._sender.disconnect(); - } + await this._sender?.disconnect(); await Promise.all( Object.values(this._exportedSenderPromises) .map((promises) => { return Object.values(promises).map((promise) => { - return promise && promise.then((sender) => { - if (sender) { - return sender.disconnect(); - } - return undefined; + return promise?.then((sender) => { + return sender?.disconnect(); }); }); }).flat(), @@ -408,7 +500,7 @@ class TelegramClient { try { await this.disconnect(); - this._sender.destroy(); + this._sender?.destroy(); } catch (err) { // Do nothing } @@ -417,9 +509,13 @@ class TelegramClient { this._eventBuilders = []; } - async _switchDC(newDc) { + async _switchDC(newDc: number) { + if (!this._sender) { + throw new Error('Sender is not initialized'); + } + this._log.info(`Reconnecting to new data center ${newDc}`); - const DC = utils.getDC(newDc); + const DC = getDC(newDc); const isTestServer = this.session.isTestServer || this._args.isTestServerRequested; this.session.setDC(newDc, DC.ipAddress, DC.port, isTestServer); // authKey's are associated with a server, which has now changed @@ -432,14 +528,14 @@ class TelegramClient { return this.connect(); } - _authKeyCallback(authKey, dcId) { + _authKeyCallback(authKey: AuthKey, dcId: number) { this.session.setAuthKey(authKey, dcId); } // endregion // export region - async _cleanupExportedSender(dcId, index) { + async _cleanupExportedSender(dcId: number, index: number) { if (this.session.dcId !== dcId) { this.session.setAuthKey(undefined, dcId); } @@ -448,10 +544,10 @@ class TelegramClient { const sender = await this._exportedSenderPromises[dcId][index]; delete this._exportedSenderPromises[dcId][index]; delete this._exportedSenderRefCounter[dcId][index]; - await sender.disconnect(); + await sender?.disconnect(); } - async _cleanupExportedSenders(dcId) { + async _cleanupExportedSenders(dcId: number) { const promises = Object.values(this._exportedSenderPromises[dcId]); if (!promises.length) { return; @@ -466,14 +562,14 @@ class TelegramClient { await Promise.all(promises.map(async (promise) => { const sender = await promise; - await sender.disconnect(); + await sender?.disconnect(); })); } - async _connectSender(sender, dcId, index, isPremium = false) { + async _connectSender(sender: MTProtoSender, dcId: number, index?: number, isPremium = false) { // if we don't already have an auth key we want to use normal DCs not -1 let hasAuthKey = Boolean(sender.authKey.getKey()); - let firstConnectResolver; + let firstConnectResolver: (() => void) | undefined; if (!hasAuthKey) { if (this._waitingForAuthKey[dcId]) { @@ -492,35 +588,35 @@ class TelegramClient { } } - const dc = utils.getDC(dcId, hasAuthKey); + const dc = getDC(dcId, hasAuthKey); // eslint-disable-next-line no-constant-condition while (true) { try { - await sender.connect(new this._connection( - dc.ipAddress, - dc.port, + await sender.connect(new this._connection({ + ip: dc.ipAddress, + port: dc.port, dcId, - this._log, - this.session.isTestServer, + loggers: this._log, + isTestServer: this.session.isTestServer, // Premium DCs are not stable for obtaining auth keys, so need to we first connect to regular ones - hasAuthKey ? isPremium : false, - ), undefined, new this._fallbackConnection( - dc.ipAddress, - dc.port, + isPremium: hasAuthKey ? isPremium : false, + }), false, new this._fallbackConnection({ + ip: dc.ipAddress, + port: dc.port, dcId, - this._log, - this.session.isTestServer, - hasAuthKey ? isPremium : false, - )); + loggers: this._log, + isTestServer: this.session.isTestServer, + isPremium: hasAuthKey ? isPremium : false, + })); if (this.session.dcId !== dcId && !sender._authenticated) { // Prevent another connection from trying to export the auth key while we're doing it await navigator.locks.request('GRAMJS_AUTH_EXPORT', async () => { this._log.info(`Exporting authorization for data center ${dc.ipAddress}`); - const auth = await this.invoke(new requests.auth.ExportAuthorization({ dcId })); + const auth = await this.invoke(new Api.auth.ExportAuthorization({ dcId })); - const req = this._initWith(new requests.auth.ImportAuthorization({ + const req = this._initWith(new Api.auth.ImportAuthorization({ id: auth.id, bytes: auth.bytes, })); @@ -529,7 +625,7 @@ class TelegramClient { }); } - sender.dcId = dcId; + sender._dcId = dcId; sender.userDisconnected = false; if (firstConnectResolver) { @@ -543,7 +639,7 @@ class TelegramClient { } return sender; - } catch (err) { + } catch (err: any) { if (this._shouldDebugExportedSenders) { // eslint-disable-next-line no-console console.error(`☠️ ERROR! idx=${index} dcId=${dcId} ${err.message}`); @@ -551,13 +647,13 @@ class TelegramClient { // eslint-disable-next-line no-console console.error(err); - await Helpers.sleep(1000); + await sleep(1000); await sender.disconnect(); } } } - releaseExportedSender(sender) { + releaseExportedSender(sender: MTProtoSender) { const dcId = sender._dcId; const index = sender._senderIndex; @@ -579,11 +675,9 @@ class TelegramClient { } } - async _borrowExportedSender(dcId, shouldReconnect, existingSender, index, isPremium) { - if (this._additionalDcsDisabled) { - return undefined; - } - + async _borrowExportedSender( + dcId: number, shouldReconnect?: boolean, existingSender?: MTProtoSender, index?: number, isPremium?: boolean, + ): Promise { const i = index || 0; if (!this._exportedSenderPromises[dcId]) this._exportedSenderPromises[dcId] = {}; @@ -608,9 +702,9 @@ class TelegramClient { try { sender = await this._exportedSenderPromises[dcId][i]; - if (!sender.isConnected()) { - if (sender.isConnecting) { - await Helpers.sleep(EXPORTED_SENDER_RECONNECT_TIMEOUT); + if (!sender?.isConnected()) { + if (sender?.isConnecting) { + await sleep(EXPORTED_SENDER_RECONNECT_TIMEOUT); return this._borrowExportedSender(dcId, false, sender, i, isPremium); } else { return this._borrowExportedSender(dcId, true, sender, i, isPremium); @@ -633,7 +727,7 @@ class TelegramClient { return sender; } - _createExportedSender(dcId, index) { + _createExportedSender(dcId: number, index: number) { return new MTProtoSender(this.session.getAuthKey(dcId), { logger: this._log, dcId, @@ -655,10 +749,10 @@ class TelegramClient { }); } - getSender(dcId, index, isPremium) { + getSender(dcId: number, index?: number, isPremium?: boolean) { return dcId ? this._borrowExportedSender(dcId, undefined, undefined, index, isPremium) - : Promise.resolve(this._sender); + : Promise.resolve(this._sender!); } // end region @@ -667,7 +761,7 @@ class TelegramClient { /** * Complete flow to download a file. - * @param inputLocation {constructors.InputFileLocation} + * @param inputLocation {Api.InputFileLocation} * @param [args[partSizeKb] {number}] * @param [args[fileSize] {number}] * @param [args[progressCallback] {Function}] @@ -678,85 +772,88 @@ class TelegramClient { * @param [args[isPriority] {boolean}] * @returns {Promise} */ - downloadFile(inputLocation, args = {}) { + downloadFile(inputLocation: Api.TypeInputFileLocation, args: DownloadFileWithDcParams) { return downloadFile(this, inputLocation, args, this._shouldDebugExportedSenders); } - downloadMedia(entityOrMedia, args) { + downloadMedia( + entityOrMedia: Api.Message | Api.TypeMessageMedia, args: DownloadMediaParams & Partial, + ) { let media; - if (entityOrMedia instanceof constructors.Message || entityOrMedia instanceof constructors.StoryItem) { + if (entityOrMedia instanceof Api.Message || entityOrMedia instanceof Api.StoryItem) { media = entityOrMedia.media; - } else if (entityOrMedia instanceof constructors.MessageService) { - media = entityOrMedia.action.photo; + } else if (entityOrMedia instanceof Api.MessageService) { + const action = entityOrMedia.action; + if ('photo' in action) { + media = action.photo; + } } else { media = entityOrMedia; } - if (typeof media === 'string') { - throw new Error('not implemented'); - } - - if (media instanceof constructors.MessageMediaWebPage) { - if (media.webpage instanceof constructors.WebPage) { + if (media instanceof Api.MessageMediaWebPage) { + if (media.webpage instanceof Api.WebPage) { media = media.webpage.document || media.webpage.photo; } } - if (media instanceof constructors.MessageMediaPhoto || media instanceof constructors.Photo) { + if (media instanceof Api.MessageMediaPhoto || media instanceof Api.Photo) { return this._downloadPhoto(media, args); - } else if (media instanceof constructors.MessageMediaDocument || media instanceof constructors.Document) { + } else if (media instanceof Api.MessageMediaDocument || media instanceof Api.Document) { return this._downloadDocument(media, args); - } else if (media instanceof constructors.MessageMediaContact) { - return this._downloadContact(media, args); - } else if (media instanceof constructors.WebDocument || media instanceof constructors.WebDocumentNoProxy) { - return this._downloadWebDocument(media, args); + } else if (media instanceof Api.WebDocument || media instanceof Api.WebDocumentNoProxy) { + return this._downloadWebDocument(media); } return undefined; } - downloadProfilePhoto(entity, isBig = false) { + downloadProfilePhoto(entity: Api.User | Api.Chat, isBig = false) { const photo = entity.photo; - if (!(photo instanceof constructors.UserProfilePhoto - || photo instanceof constructors.ChatPhoto)) return undefined; + if (!(photo instanceof Api.UserProfilePhoto + || photo instanceof Api.ChatPhoto)) return undefined; const dcId = photo.dcId; - const loc = new constructors.InputPeerPhotoFileLocation({ - peer: utils.getInputPeer(entity), + const loc = new Api.InputPeerPhotoFileLocation({ + peer: getInputPeer(entity), photoId: photo.photoId, - big: isBig, + big: isBig || undefined, }); return this.downloadFile(loc, { dcId, isPriority: true, - }); + }) as Promise; // Profile photo cannot be larger than 2GB, right? } - downloadStickerSetThumb(stickerSet) { + downloadStickerSetThumb(stickerSet: Api.StickerSet) { if (!stickerSet.thumbs?.length && !stickerSet.thumbDocumentId) { return undefined; } - const { thumbVersion } = stickerSet; + const thumbVersion = stickerSet.thumbVersion!; if (!stickerSet.thumbDocumentId) { return this.downloadFile( - new constructors.InputStickerSetThumb({ - stickerset: new constructors.InputStickerSetID({ + new Api.InputStickerSetThumb({ + stickerset: new Api.InputStickerSetID({ id: stickerSet.id, accessHash: stickerSet.accessHash, }), thumbVersion, }), - { dcId: stickerSet.thumbDcId }, - ); + { dcId: stickerSet.thumbDcId! }, + ) as Promise; // Sticker thumb cannot be larger than 2GB, right? } - return this.invoke(new constructors.messages.GetCustomEmojiDocuments({ + return this.invoke(new Api.messages.GetCustomEmojiDocuments({ documentId: [stickerSet.thumbDocumentId], })).then((docs) => { const doc = docs[0]; - return this.downloadFile(new constructors.InputDocumentFileLocation({ + if (!doc || doc instanceof Api.DocumentEmpty) { + return undefined; + } + + return this.downloadFile(new Api.InputDocumentFileLocation({ id: doc.id, accessHash: doc.accessHash, fileReference: doc.fileReference, @@ -765,62 +862,103 @@ class TelegramClient { { fileSize: doc.size.toJSNumber(), dcId: doc.dcId, - }); + }) as Promise; // Sticker thumb cannot be larger than 2GB, right? }); } - _pickFileSize(sizes, sizeType) { - if (!sizeType || !sizes || !sizes.length) { - return undefined; + getThumb( + thumbs: (Api.TypePhotoSize | Api.TypeVideoSize)[], + thumb?: string | Api.TypePhotoSize | Api.VideoSize + ) { + function sortThumb(thumb: Api.TypePhotoSize | Api.TypeVideoSize) { + if (thumb instanceof Api.PhotoStrippedSize) { + return thumb.bytes.length; + } + if (thumb instanceof Api.PhotoCachedSize) { + return thumb.bytes.length; + } + if (thumb instanceof Api.PhotoSize) { + return thumb.size; + } + if (thumb instanceof Api.PhotoSizeProgressive) { + return Math.max(...thumb.sizes); + } + if (thumb instanceof Api.VideoSize) { + return thumb.size; + } + return 0; } - const indexOfSize = sizeTypes.indexOf(sizeType); - let size; - for (let i = indexOfSize; i < sizeTypes.length; i++) { - size = sizes.find((s) => s.type === sizeTypes[i]); - if (size) { - return size; + + thumbs = thumbs.sort((a, b) => sortThumb(a) - sortThumb(b)); + const correctThumbs = []; + for (const t of thumbs) { + if (!(t instanceof Api.PhotoPathSize)) { + correctThumbs.push(t); } } - return undefined; + if (thumb == undefined) { + return correctThumbs.pop(); + } else if (typeof thumb == "string") { + for (const t of correctThumbs) { + if ("type" in t && t.type == thumb) { + return t; + } + } + } else if ( + thumb instanceof Api.PhotoSize || + thumb instanceof Api.PhotoCachedSize || + thumb instanceof Api.PhotoStrippedSize || + thumb instanceof Api.VideoSize + ) { + return thumb; + } } - _downloadCachedPhotoSize(size) { + _downloadCachedPhotoSize(size: Api.PhotoCachedSize | Api.PhotoStrippedSize) { // No need to download anything, simply write the bytes let data; - if (size instanceof constructors.PhotoStrippedSize) { - data = utils.strippedPhotoToJpg(size.bytes); + if (size instanceof Api.PhotoStrippedSize) { + data = strippedPhotoToJpg(size.bytes); } else { data = size.bytes; } return data; } - _downloadPhoto(photo, args) { - if (photo instanceof constructors.MessageMediaPhoto) { - photo = photo.photo; + _downloadPhoto(media: Api.MessageMediaPhoto | Api.TypePhoto, args: DownloadMediaParams) { + let photo = media; + if (media instanceof Api.MessageMediaPhoto && media.photo instanceof Api.Photo) { + photo = media.photo; } - if (!(photo instanceof constructors.Photo)) { + + if (!(photo instanceof Api.Photo)) { return undefined; } - const maxSize = photo.sizes.reduce((max, current) => { - if (!current.w) return max; - return max.w > current.w ? max : current; - }); const isVideoSize = args.sizeType === 'u' || args.sizeType === 'v'; - const size = !args.sizeType - ? maxSize - : this._pickFileSize(isVideoSize ? [...photo.videoSizes, ...photo.sizes] : photo.sizes, args.sizeType); + const videoSizes = isVideoSize ? photo.videoSizes! : []; + const size = this.getThumb([...videoSizes, ...photo.sizes], args.sizeType); - if (!size || (size instanceof constructors.PhotoSizeEmpty)) { + if (!size + || size instanceof Api.PhotoSizeEmpty + || size instanceof Api.VideoSizeEmojiMarkup + || size instanceof Api.VideoSizeStickerMarkup) { return undefined; } - if (size instanceof constructors.PhotoCachedSize || size instanceof constructors.PhotoStrippedSize) { + if (size instanceof Api.PhotoCachedSize || size instanceof Api.PhotoStrippedSize) { return this._downloadCachedPhotoSize(size); } + + let fileSize: number; + if (size instanceof Api.PhotoSizeProgressive) { + fileSize = Math.max(...size.sizes); + } else { + fileSize = "size" in size ? size.size : 512; + } + return this.downloadFile( - new constructors.InputPhotoFileLocation({ + new Api.InputPhotoFileLocation({ id: photo.id, accessHash: photo.accessHash, fileReference: photo.fileReference, @@ -828,43 +966,45 @@ class TelegramClient { }), { dcId: photo.dcId, - fileSize: size.size || Math.max(...(size.sizes || [])), + fileSize, progressCallback: args.progressCallback, }, ); } - _downloadDocument(doc, args) { - if (doc instanceof constructors.MessageMediaDocument) { + _downloadDocument( + media: Api.MessageMediaDocument | Api.TypeDocument, args: DownloadMediaParams & DownloadFileParams, + ) { + let doc = media; + if (doc instanceof Api.MessageMediaDocument && doc.document instanceof Api.Document) { doc = doc.document; } - if (!(doc instanceof constructors.Document)) { + if (!(doc instanceof Api.Document)) { return undefined; } let size; if (args.sizeType) { - size = doc.thumbs ? this._pickFileSize([...(doc.videoThumbs || []), - ...doc.thumbs], args.sizeType) : undefined; + size = this.getThumb([...(doc.thumbs || []), ...(doc.videoThumbs || [])], args.sizeType); if (!size && doc.mimeType.startsWith('video/')) { return undefined; } - if (size && (size instanceof constructors.PhotoCachedSize - || size instanceof constructors.PhotoStrippedSize)) { + if (size && (size instanceof Api.PhotoCachedSize + || size instanceof Api.PhotoStrippedSize)) { return this._downloadCachedPhotoSize(size); } } return this.downloadFile( - new constructors.InputDocumentFileLocation({ + new Api.InputDocumentFileLocation({ id: doc.id, accessHash: doc.accessHash, fileReference: doc.fileReference, - thumbSize: size ? size.type : '', + thumbSize: size && "type" in size ? size.type : "", }), { - fileSize: size ? size.size : doc.size.toJSNumber(), + fileSize: size && "size" in size ? size.size : doc.size.toJSNumber(), progressCallback: args.progressCallback, start: args.start, end: args.end, @@ -874,13 +1014,8 @@ class TelegramClient { ); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _downloadContact(media, args) { - throw new Error('not implemented'); - } - - async _downloadWebDocument(media) { - if (media.url && !('accessHash' in media)) { + async _downloadWebDocument(media: Api.TypeWebDocument) { + if (media instanceof Api.WebDocumentNoProxy) { const arrayBuff = await fetch(media.url).then((res) => res.arrayBuffer()); return Buffer.from(arrayBuff); } @@ -890,8 +1025,8 @@ class TelegramClient { let offset = 0; // eslint-disable-next-line no-constant-condition while (true) { - const downloaded = new requests.upload.GetWebFile({ - location: new constructors.InputWebFileLocation({ + const downloaded = new Api.upload.GetWebFile({ + location: new Api.InputWebFileLocation({ url: media.url, accessHash: media.accessHash, }), @@ -902,9 +1037,12 @@ class TelegramClient { const sender = await this._borrowExportedSender( this._config?.webfileDcId || DEFAULT_WEBDOCUMENT_DC_ID, ); - const res = await sender.send(downloaded); + if (!sender) { + throw new Error('Failed to obtain sender'); + } + const res = (await sender.send(downloaded))!; this.releaseExportedSender(sender); - offset += 131072; + offset += WEBDOCUMENT_REQUEST_PART_SIZE; if (res.bytes.length) { buff.push(res.bytes); if (res.bytes.length < WEBDOCUMENT_REQUEST_PART_SIZE) { @@ -915,26 +1053,35 @@ class TelegramClient { } } return Buffer.concat(buff); - } catch (e) { + } catch (err: unknown) { // the file is no longer saved in telegram's cache. - if (e.message === 'WEBFILE_NOT_AVAILABLE') { + if (err instanceof RPCError && err.errorMessage === 'WEBFILE_NOT_AVAILABLE') { return Buffer.alloc(0); } else { - throw e; + throw err; } } } - async downloadStaticMap(accessHash, long, lat, w, h, zoom, scale, accuracyRadius) { + async downloadStaticMap( + accessHash: bigInt.BigInteger, + long: number, + lat: number, + w: number, + h: number, + zoom: number, + scale: number, + accuracyRadius?: number, + ) { try { const buff = []; let offset = 0; // eslint-disable-next-line no-constant-condition while (true) { try { - const downloaded = new requests.upload.GetWebFile({ - location: new constructors.InputWebFileGeoPointLocation({ - geoPoint: new constructors.InputGeoPoint({ + const downloaded = new Api.upload.GetWebFile({ + location: new Api.InputWebFileGeoPointLocation({ + geoPoint: new Api.InputGeoPoint({ lat, long, accuracyRadius, @@ -949,9 +1096,12 @@ class TelegramClient { limit: WEBDOCUMENT_REQUEST_PART_SIZE, }); const sender = await this._borrowExportedSender(DEFAULT_WEBDOCUMENT_DC_ID); - const res = await sender.send(downloaded); + if (!sender) { + throw new Error('Failed to obtain sender'); + } + const res = (await sender.send(downloaded))!; this.releaseExportedSender(sender); - offset += 131072; + offset += WEBDOCUMENT_REQUEST_PART_SIZE; if (res.bytes.length) { buff.push(res.bytes); if (res.bytes.length < WEBDOCUMENT_REQUEST_PART_SIZE) { @@ -961,7 +1111,7 @@ class TelegramClient { break; } } catch (err) { - if (err instanceof errors.FloodWaitError) { + if (err instanceof FloodWaitError) { // eslint-disable-next-line no-console console.warn(`getWebFile: sleeping for ${err.seconds}s on flood wait`); await sleep(err.seconds * 1000); @@ -970,12 +1120,11 @@ class TelegramClient { } } return Buffer.concat(buff); - } catch (e) { - // the file is no longer saved in telegram's cache. - if (e.message === 'WEBFILE_NOT_AVAILABLE') { + } catch (err: unknown) { + if (err instanceof RPCError && err.errorMessage === 'WEBFILE_NOT_AVAILABLE') { return Buffer.alloc(0); } else { - throw e; + throw err; } } } @@ -990,13 +1139,15 @@ class TelegramClient { * @returns {Promise} */ - async invoke(request, dcId, abortSignal, shouldRetryOnTimeout = false) { + async invoke( + request: R, dcId?: number, abortSignal?: AbortSignal, shouldRetryOnTimeout?: boolean, + ): Promise { if (request.classType !== 'request') { throw new Error('You can only invoke MTProtoRequests'); } const isExported = dcId !== undefined; - let sender = !isExported ? this._sender : await this.getSender(dcId); + let sender = (!isExported ? this._sender : await this.getSender(dcId))!; this._lastRequest = Date.now(); await this._connectedDeferred.promise; @@ -1011,15 +1162,17 @@ class TelegramClient { state.finished.resolve(); if (isExported) this.releaseExportedSender(sender); return result; - } catch (e) { - if (e instanceof errors.ServerError - || e.message === 'RPC_CALL_FAIL' - || e.message === 'RPC_MCGET_FAIL' - || e.message.match(/INTERDC_\d_CALL(_RICH)?_ERROR/) + } catch (e: unknown) { + if (e instanceof ServerError + || (e instanceof RPCError && ( + e.errorMessage === 'RPC_CALL_FAIL' + || e.errorMessage === 'RPC_MCGET_FAIL' + || e.errorMessage.match(/INTERDC_\d_CALL(_RICH)?_ERROR/) + )) ) { this._log.warn(`Telegram is having internal issues ${e.constructor.name}`); await sleep(2000); - } else if (e instanceof errors.FloodWaitError || e instanceof errors.FloodTestPhoneWaitError) { + } else if (e instanceof FloodWaitError || e instanceof FloodTestPhoneWaitError) { if (e.seconds <= this.floodSleepLimit) { this._log.info(`Sleeping for ${e.seconds}s on flood wait`); await sleep(e.seconds * 1000); @@ -1028,11 +1181,11 @@ class TelegramClient { if (isExported) this.releaseExportedSender(sender); throw e; } - } else if (e instanceof errors.PhoneMigrateError || e instanceof errors.NetworkMigrateError - || e instanceof errors.UserMigrateError) { + } else if (e instanceof PhoneMigrateError || e instanceof NetworkMigrateError + || e instanceof UserMigrateError) { this._log.info(`Phone migrated to ${e.newDc}`); - const shouldRaise = e instanceof errors.PhoneMigrateError - || e instanceof errors.NetworkMigrateError; + const shouldRaise = e instanceof PhoneMigrateError + || e instanceof NetworkMigrateError; if (shouldRaise && await checkAuthorization(this)) { state.finished.resolve(); if (isExported) this.releaseExportedSender(sender); @@ -1040,17 +1193,17 @@ class TelegramClient { } await this._switchDC(e.newDc); if (isExported) this.releaseExportedSender(sender); - sender = dcId === undefined ? this._sender : await this.getSender(dcId); - } else if (e instanceof errors.MsgWaitError) { + sender = (dcId === undefined ? this._sender : await this.getSender(dcId))!; + } else if (e instanceof MsgWaitError) { // We need to resend this after the old one was confirmed. await state.isReady(); state.after = undefined; - } else if (e.message === 'CONNECTION_NOT_INITED') { + } else if (e instanceof RPCError && e.errorMessage === 'CONNECTION_NOT_INITED') { await this.disconnect(); await sleep(2000); await this.connect(); - } else if (e instanceof errors.TimedOutError) { + } else if (e instanceof TimedOutError) { if (!shouldRetryOnTimeout) { state.finished.resolve(); if (isExported) this.releaseExportedSender(sender); @@ -1069,28 +1222,31 @@ class TelegramClient { throw new Error(`Request was unsuccessful ${attempt} time(s)`); } - async invokeBeacon(request, dcId) { + async invokeBeacon(request: Api.AnyRequest, dcId?: number) { if (request.classType !== 'request') { throw new Error('You can only invoke MTProtoRequests'); } const isExported = dcId !== undefined; - const sender = !isExported ? this._sender : await this.getSender(dcId); + const sender = (!isExported ? this._sender : await this.getSender(dcId))!; sender.sendBeacon(request); if (isExported) this.releaseExportedSender(sender); } - setIsPremium(isPremium) { + setIsPremium(isPremium: boolean) { this.isPremium = isPremium; } async getMe() { try { - return (await this.invoke(new requests.users - .GetUsers({ id: [new constructors.InputUserSelf()] })))[0]; - } catch (e) { + return (await this.invoke( + new Api.users.GetUsers({ + id: [new Api.InputUserSelf()], + }) + ))[0]; + } catch (e: any) { this._log.warn('error while getting me'); this._log.warn(e); } @@ -1099,11 +1255,11 @@ class TelegramClient { async loadConfig() { if (!this._config) { - this._config = await this.invoke(new requests.help.GetConfig()); + this._config = await this.invoke(new Api.help.GetConfig()); } } - async start(authParams) { + async start(authParams: UserAuthParams) { if (!this.isConnected()) { await this.connect(); } @@ -1122,46 +1278,46 @@ class TelegramClient { await authFlow(this, apiCredentials, authParams); } - uploadFile(fileParams) { + uploadFile(fileParams: UploadFileParams) { return uploadFile(this, fileParams, this._shouldDebugExportedSenders); } - updateTwoFaSettings(params) { + updateTwoFaSettings(params: TwoFaParams) { return updateTwoFaSettings(this, params); } - getTmpPassword(currentPassword, ttl) { + getTmpPassword(currentPassword: string, ttl?: number): Promise { return getTmpPassword(this, currentPassword, ttl); } - getCurrentPassword(currentPassword) { - return getCurrentPassword(this, currentPassword); + getCurrentPassword(params: TwoFaPasswordParams): Promise { + return getCurrentPassword(this, params); } // event region - addEventHandler(callback, event) { + addEventHandler(callback: CallableFunction, event: EventBuilder) { this._eventBuilders.push([event, callback]); } - _handleUpdate(update) { + _handleUpdate(update: Update) { // this.session.processEntities(update) // this._entityCache.add(update) - if (update instanceof constructors.Updates || update instanceof constructors.UpdatesCombined) { + if (update instanceof Api.Updates || update instanceof Api.UpdatesCombined) { // TODO deal with entities const entities = []; for (const x of [...update.users, ...update.chats]) { entities.push(x); } this._processUpdate(update, entities); - } else if (update instanceof constructors.UpdateShort) { + } else if (update instanceof Api.UpdateShort) { this._processUpdate(update.update, undefined); } else { this._processUpdate(update, undefined); } } - _processUpdate(update, entities) { + _processUpdate(update: Update, entities: (Api.TypeUser | Api.TypeChat)[] | undefined) { update._entities = entities || []; const args = { update, @@ -1171,235 +1327,8 @@ class TelegramClient { // endregion - // region private methods - - /** - Gets a full entity from the given string, which may be a phone or - a username, and processes all the found entities on the session. - The string may also be a user link, or a channel/chat invite link. - - This method has the side effect of adding the found users to the - session database, so it can be queried later without API calls, - if this option is enabled on the session. - - Returns the found entity, or raises TypeError if not found. - * @param string {string} - * @returns {Promise} - * @private - */ - /* CONTEST - async _getEntityFromString(string) { - const phone = utils.parsePhone(string) - if (phone) { - try { - for (const user of (await this.invoke( - new requests.contacts.GetContacts(0))).users) { - if (user.phone === phone) { - return user - } - } - } catch (e) { - if (e.message === 'BOT_METHOD_INVALID') { - throw new Error('Cannot get entity by phone number as a ' + - 'bot (try using integer IDs, not strings)') - } - throw e - } - } else if (['me', 'this'].includes(string.toLowerCase())) { - return this.getMe() - } else { - const { username, isJoinChat } = utils.parseUsername(string) - if (isJoinChat) { - const invite = await this.invoke(new requests.messages.CheckChatInvite({ - 'hash': username, - })) - if (invite instanceof constructors.ChatInvite) { - throw new Error('Cannot get entity from a channel (or group) ' + - 'that you are not part of. Join the group and retry', - ) - } else if (invite instanceof constructors.ChatInviteAlready) { - return invite.chat - } - } else if (username) { - try { - const result = await this.invoke( - new requests.contacts.ResolveUsername(username)) - const pid = utils.getPeerId(result.peer, false) - if (result.peer instanceof constructors.PeerUser) { - for (const x of result.users) { - if (x.id === pid) { - return x - } - } - } else { - for (const x of result.chats) { - if (x.id === pid) { - return x - } - } - } - } catch (e) { - if (e.message === 'USERNAME_NOT_OCCUPIED') { - throw new Error(`No user has "${username}" as username`) - } - throw e - } - } - } - throw new Error(`Cannot find any entity corresponding to "${string}"`) - } - */ - // endregion - - // users region - /** - Turns the given entity into its input entity version. - - Most requests use this kind of :tl:`InputPeer`, so this is the most - suitable call to make for those cases. **Generally you should let the - library do its job** and don't worry about getting the input entity - first, but if you're going to use an entity often, consider making the - call: - - Arguments - entity (`str` | `int` | :tl:`Peer` | :tl:`InputPeer`): - If a username or invite link is given, **the library will - use the cache**. This means that it's possible to be using - a username that *changed* or an old invite link (this only - happens if an invite link for a small group chat is used - after it was upgraded to a mega-group). - - If the username or ID from the invite link is not found in - the cache, it will be fetched. The same rules apply to phone - numbers (``'+34 123456789'``) from people in your contact list. - - If an exact name is given, it must be in the cache too. This - is not reliable as different people can share the same name - and which entity is returned is arbitrary, and should be used - only for quick tests. - - If a positive integer ID is given, the entity will be searched - in cached users, chats or channels, without making any call. - - If a negative integer ID is given, the entity will be searched - exactly as either a chat (prefixed with ``-``) or as a channel - (prefixed with ``-100``). - - If a :tl:`Peer` is given, it will be searched exactly in the - cache as either a user, chat or channel. - - If the given object can be turned into an input entity directly, - said operation will be done. - - Unsupported types will raise ``TypeError``. - - If the entity can't be found, ``ValueError`` will be raised. - - Returns - :tl:`InputPeerUser`, :tl:`InputPeerChat` or :tl:`InputPeerChannel` - or :tl:`InputPeerSelf` if the parameter is ``'me'`` or ``'self'``. - - If you need to get the ID of yourself, you should use - `get_me` with ``input_peer=True``) instead. - - Example - .. code-block:: python - - // If you're going to use "username" often in your code - // (make a lot of calls), consider getting its input entity - // once, and then using the "user" everywhere instead. - user = await client.get_input_entity('username') - - // The same applies to IDs, chats or channels. - chat = await client.get_input_entity(-123456789) - - * @param peer - * @returns {Promise<>} - */ - - /* CONTEST - async getInputEntity(peer) { - // Short-circuit if the input parameter directly maps to an InputPeer - try { - return utils.getInputPeer(peer) - // eslint-disable-next-line no-empty - } catch (e) { - } - // Next in priority is having a peer (or its ID) cached in-memory - try { - // 0x2d45687 == crc32(b'Peer') - if (typeof peer === 'number' || peer.SUBCLASS_OF_ID === 0x2d45687) { - if (this._entityCache.has(peer)) { - return this._entityCache[peer] - } - } - // eslint-disable-next-line no-empty - } catch (e) { - } - // Then come known strings that take precedence - if (['me', 'this'].includes(peer)) { - return new constructors.InputPeerSelf() - } - // No InputPeer, cached peer, or known string. Fetch from disk cache - try { - return this.session.getInputEntity(peer) - // eslint-disable-next-line no-empty - } catch (e) { - } - // Only network left to try - if (typeof peer === 'string') { - return utils.getInputPeer(await this._getEntityFromString(peer)) - } - // If we're a bot and the user has messaged us privately users.getUsers - // will work with accessHash = 0. Similar for channels.getChannels. - // If we're not a bot but the user is in our contacts, it seems to work - // regardless. These are the only two special-cased requests. - peer = utils.getPeer(peer) - if (peer instanceof constructors.PeerUser) { - const users = await this.invoke(new requests.users.GetUsers({ - id: [new constructors.InputUser({ - userId: peer.userId, - accessHash: 0, - })], - })) - if (users && !(users[0] instanceof constructors.UserEmpty)) { - // If the user passed a valid ID they expect to work for - // channels but would be valid for users, we get UserEmpty. - // Avoid returning the invalid empty input peer for that. - // - // We *could* try to guess if it's a channel first, and if - // it's not, work as a chat and try to validate it through - // another request, but that becomes too much work. - return utils.getInputPeer(users[0]) - } - } else if (peer instanceof constructors.PeerChat) { - return new constructors.InputPeerChat({ - chatId: peer.chatId, - }) - } else if (peer instanceof constructors.PeerChannel) { - try { - const channels = await this.invoke(new requests.channels.GetChannels({ - id: [new constructors.InputChannel({ - channelId: peer.channelId, - accessHash: 0, - })], - })) - - return utils.getInputPeer(channels.chats[0]) - // eslint-disable-next-line no-empty - } catch (e) { - console.log(e) - } - } - throw new Error(`Could not find the input entity for ${peer.id || peer.channelId || peer.chatId || peer.userId}. - Please read https://` + - 'docs.telethon.dev/en/latest/concepts/entities.html to' + - ' find out more details.', - ) - } - */ - async _dispatchUpdate(args = { - update: undefined, + async _dispatchUpdate(args: { + update: Update, }) { for (const [builder, callback] of this._eventBuilders) { const event = builder.build(args.update); @@ -1419,18 +1348,18 @@ class TelegramClient { } } -function timeout(cb, ms) { +function timeout(cb: () => void, ms: number) { let isResolved = false; return Promise.race([ cb(), - Helpers.sleep(ms).then(() => (isResolved ? undefined : Promise.reject(new Error('TIMEOUT')))), + sleep(ms).then(() => (isResolved ? undefined : Promise.reject(new Error('TIMEOUT')))), ]).finally(() => { isResolved = true; }); } -async function attempts(cb, times, pause) { +async function attempts(cb: () => void, times: number, pause: number) { for (let i = 0; i < times; i++) { try { // We need to `return await` here so it can be caught locally @@ -1441,10 +1370,10 @@ async function attempts(cb, times, pause) { throw err; } - await Helpers.sleep(pause); + await sleep(pause); } } return undefined; } -module.exports = TelegramClient; +export default TelegramClient; diff --git a/src/lib/gramjs/client/auth.ts b/src/lib/gramjs/client/auth.ts index 2846876ba..f21e1a25e 100644 --- a/src/lib/gramjs/client/auth.ts +++ b/src/lib/gramjs/client/auth.ts @@ -4,7 +4,9 @@ import Api from '../tl/api'; import { sleep } from '../Helpers'; import { computeCheck as computePasswordSrpCheck } from '../Password'; -import utils from '../Utils'; +import { getDisplayName } from '../Utils'; +import { Update } from './TelegramClient'; +import { RPCError } from '../errors'; export interface UserAuthParams { phoneNumber: string | (() => Promise); @@ -48,7 +50,7 @@ export async function authFlow( me = await signInUserWithPreferredMethod(client, apiCredentials, authParams); } - client._log.info('Signed in successfully as', utils.getDisplayName(me)); + client._log.info(`Signed in successfully as ${getDisplayName(me)}`); } export function signInUserWithPreferredMethod( @@ -67,8 +69,8 @@ export async function checkAuthorization(client: TelegramClient, shouldThrow = f try { await client.invoke(new Api.updates.GetState()); return true; - } catch (e: any) { - if (e.message === 'Disconnect' || shouldThrow) throw e; + } catch (err: unknown) { + if ((err instanceof RPCError && err.errorMessage === 'Disconnect') || shouldThrow) throw err; return false; } } @@ -89,8 +91,8 @@ async function signInUserWithWebToken( } else { throw new Error('SIGN_UP_REQUIRED'); } - } catch (err: any) { - if (err.message === 'SESSION_PASSWORD_NEEDED') { + } catch (err: unknown) { + if (err instanceof RPCError && err.errorMessage === 'SESSION_PASSWORD_NEEDED') { return signInWithPassword(client, apiCredentials, authParams, true); } else { client._log.error(`Failed to login with web token: ${err}`); @@ -116,8 +118,8 @@ async function signInUser( if (typeof authParams.phoneNumber === 'function') { try { phoneNumber = await authParams.phoneNumber(); - } catch (err: any) { - if (err.message === 'RESTART_AUTH_WITH_QR') { + } catch (err: unknown) { + if (err instanceof Error && err.message === 'RESTART_AUTH_WITH_QR') { return signInUserWithQrCode(client, apiCredentials, authParams); } @@ -153,9 +155,9 @@ async function signInUser( try { try { phoneCode = await authParams.phoneCode(isCodeViaApp); - } catch (err: any) { + } catch (err: unknown) { // This is the support for changing phone number from the phone code screen. - if (err.message === 'RESTART_AUTH') { + if (err instanceof Error && err.message === 'RESTART_AUTH') { return signInUser(client, apiCredentials, authParams); } } @@ -179,11 +181,13 @@ async function signInUser( } return result.user; - } catch (err: any) { - if (err.message === 'SESSION_PASSWORD_NEEDED') { + } catch (err: unknown) { + if (err instanceof RPCError && err.errorMessage === 'SESSION_PASSWORD_NEEDED') { return signInWithPassword(client, apiCredentials, authParams); - } else { + } else if (err instanceof Error) { authParams.onError(err); + } else { + console.warn('Unexpected error:', err); } } } @@ -255,15 +259,15 @@ async function signInUserWithQrCode( if (update instanceof Api.UpdateLoginToken) { resolve(); } - }, { build: (update: object) => update }); + }, { build: (update: Update) => update }); }); try { // Either we receive an update that QR is successfully scanned, // or we receive a rejection caused by user going back to the regular auth form await Promise.race([updatePromise, inputPromise]); - } catch (err: any) { - if (err.message === 'RESTART_AUTH') { + } catch (err: unknown) { + if (err instanceof Error && err.message === 'RESTART_AUTH') { return await signInUser(client, apiCredentials, authParams); } @@ -292,8 +296,8 @@ async function signInUserWithQrCode( return migratedResult.authorization.user; } } - } catch (err: any) { - if (err.message === 'SESSION_PASSWORD_NEEDED') { + } catch (err: unknown) { + if (err instanceof RPCError && err.errorMessage === 'SESSION_PASSWORD_NEEDED') { return signInWithPassword(client, apiCredentials, authParams); } @@ -345,8 +349,8 @@ async function sendCode( phoneCodeHash: resendResult.phoneCodeHash, isCodeViaApp: resendResult.type instanceof Api.auth.SentCodeTypeApp, }; - } catch (err: any) { - if (err.message === 'AUTH_RESTART') { + } catch (err: unknown) { + if (err instanceof RPCError && err.errorMessage === 'AUTH_RESTART') { return sendCode(client, apiCredentials, phoneNumber, forceSMS); } else { throw err; diff --git a/src/lib/gramjs/client/downloadFile.ts b/src/lib/gramjs/client/downloadFile.ts index fab7ae1dc..b5fbe94d2 100644 --- a/src/lib/gramjs/client/downloadFile.ts +++ b/src/lib/gramjs/client/downloadFile.ts @@ -4,12 +4,13 @@ import type TelegramClient from './TelegramClient'; import Deferred from '../../../util/Deferred'; import { Foreman } from '../../../util/foreman'; -import errors from '../errors'; +import { FloodPremiumWaitError, FloodWaitError, RPCError } from '../errors'; import Api from '../tl/api'; import LocalUpdatePremiumFloodWait from '../../../api/gramjs/updates/UpdatePremiumFloodWait'; import { sleep } from '../Helpers'; import { getDownloadPartSize } from '../Utils'; +import type { SizeType } from './TelegramClient'; interface OnProgress { isCanceled?: boolean; @@ -20,8 +21,7 @@ interface OnProgress { } export interface DownloadFileParams { - dcId: number; - fileSize: number; + fileSize?: number; workers?: number; partSizeKb?: number; start?: number; @@ -30,6 +30,13 @@ export interface DownloadFileParams { isPriority?: boolean; } +export type DownloadFileWithDcParams = DownloadFileParams & { dcId: number }; + +export interface DownloadMediaParams { + sizeType?: SizeType; + progressCallback?: OnProgress; +} + // Chunk sizes for `upload.getFile` must be multiple of the smallest size const MIN_CHUNK_SIZE = 4096; const DEFAULT_CHUNK_SIZE = 64; // kb @@ -87,7 +94,7 @@ class FileView { } } - getData(): Promise { + async getData(): Promise { if (this.type === 'opfs') { return this.largeFile!.getFile(); } else { @@ -98,19 +105,19 @@ class FileView { export async function downloadFile( client: TelegramClient, - inputLocation: Api.InputFileLocation, - fileParams: DownloadFileParams, + inputLocation: Api.TypeInputFileLocation, + fileParams: DownloadFileWithDcParams, shouldDebugExportedSenders?: boolean, ) { const { dcId } = fileParams; for (let i = 0; i < SENDER_RETRIES; i++) { try { return await downloadFile2(client, inputLocation, fileParams, shouldDebugExportedSenders); - } catch (err: any) { - if ( - (err.message.startsWith('SESSION_REVOKED') || err.message.startsWith('CONNECTION_NOT_INITED')) - && i < SENDER_RETRIES - 1 - ) { + } catch (err: unknown) { + if (err instanceof RPCError && ( + err.errorMessage.startsWith('SESSION_REVOKED') + || err.errorMessage.startsWith('CONNECTION_NOT_INITED') + ) && i < SENDER_RETRIES - 1) { await client._cleanupExportedSenders(dcId); } else { throw err; @@ -131,12 +138,12 @@ const foremans = Array(MAX_CONCURRENT_CONNECTIONS_PREMIUM).fill(undefined) async function downloadFile2( client: TelegramClient, - inputLocation: Api.InputFileLocation, - fileParams: DownloadFileParams, + inputLocation: Api.TypeInputFileLocation, + fileParams: DownloadFileWithDcParams, shouldDebugExportedSenders?: boolean, ) { let { - partSizeKb, end, + partSizeKb, end = 0, } = fileParams; const { fileSize, dcId, progressCallback, isPriority, start = 0, @@ -152,14 +159,18 @@ async function downloadFile2( logWithId('Downloading file...'); const isPremium = Boolean(client.isPremium); - end = end && end < fileSize ? end : fileSize - 1; + if (fileSize) { + end = end && end < fileSize ? end : fileSize - 1; + } + + const rangeSize = end ? end - start + 1 : undefined; if (!partSizeKb) { - partSizeKb = fileSize ? getDownloadPartSize(start ? (end - start + 1) : fileSize) : DEFAULT_CHUNK_SIZE; + partSizeKb = fileSize ? getDownloadPartSize(rangeSize || fileSize) : DEFAULT_CHUNK_SIZE; } const partSize = partSizeKb * 1024; - const partsCount = end ? Math.ceil((end + 1 - start + 1) / partSize) : 1; + const partsCount = rangeSize ? Math.ceil(rangeSize / partSize) : 1; const noParallel = !end; const shouldUseMultipleConnections = Boolean(fileSize) && fileSize >= MULTIPLE_CONNECTIONS_MIN_FILE_SIZE @@ -172,7 +183,7 @@ async function downloadFile2( client._log.info(`Downloading file in chunks of ${partSize} bytes`); - const fileView = new FileView(end - start + 1); + const fileView = new FileView(rangeSize); const promises: Promise[] = []; let offset = start; // Used for files with unknown size and for manual cancellations @@ -243,7 +254,7 @@ async function downloadFile2( }, 6000); } // sometimes a session is revoked and will cause this to hang. - const result = await Promise.race([ + const result = (await Promise.race([ sender.send(new Api.upload.GetFile({ location: inputLocation, offset: BigInt(offsetMemo), @@ -260,9 +271,13 @@ async function downloadFile2( return Promise.reject(new Error('SESSION_REVOKED')); } }), - ]); + ]))!; client.releaseExportedSender(sender); + if (result instanceof Api.upload.FileCdnRedirect) { + throw new Error('CDN download not supported'); + } + isDone2 = true; if (progressCallback) { if (progressCallback.isCanceled) { @@ -288,8 +303,8 @@ async function downloadFile2( if (sender && !sender.isConnected()) { await sleep(DISCONNECT_SLEEP); continue; - } else if (err instanceof errors.FloodWaitError) { - if (err instanceof errors.FloodPremiumWaitError && !isPremiumFloodWaitSent) { + } else if (err instanceof FloodWaitError) { + if (err instanceof FloodPremiumWaitError && !isPremiumFloodWaitSent) { sender?._updateCallback(new LocalUpdatePremiumFloodWait(false)); isPremiumFloodWaitSent = true; } @@ -302,7 +317,7 @@ async function downloadFile2( if (deferred) deferred.resolve(); hasEnded = true; - client.releaseExportedSender(sender); + if (sender) client.releaseExportedSender(sender); throw err; } } diff --git a/src/lib/gramjs/client/uploadFile.ts b/src/lib/gramjs/client/uploadFile.ts index bbcbe29d9..f846798fb 100644 --- a/src/lib/gramjs/client/uploadFile.ts +++ b/src/lib/gramjs/client/uploadFile.ts @@ -1,7 +1,7 @@ import type TelegramClient from './TelegramClient'; import { Foreman } from '../../../util/foreman'; -import errors from '../errors'; +import { FloodPremiumWaitError, FloodWaitError } from '../errors'; import Api from '../tl/api'; import LocalUpdatePremiumFloodWait from '../../../api/gramjs/updates/UpdatePremiumFloodWait'; @@ -133,8 +133,8 @@ export async function uploadFile( if (sender && !sender.isConnected()) { await sleep(DISCONNECT_SLEEP); continue; - } else if (err instanceof errors.FloodWaitError) { - if (err instanceof errors.FloodPremiumWaitError && !isPremiumFloodWaitSent) { + } else if (err instanceof FloodWaitError) { + if (err instanceof FloodPremiumWaitError && !isPremiumFloodWaitSent) { sender?._updateCallback(new LocalUpdatePremiumFloodWait(true)); isPremiumFloodWaitSent = true; } @@ -142,7 +142,7 @@ export async function uploadFile( continue; } foremans[senderIndex].releaseWorker(); - client.releaseExportedSender(sender); + if (sender) client.releaseExportedSender(sender); throw err; } diff --git a/src/lib/gramjs/crypto/AuthKey.js b/src/lib/gramjs/crypto/AuthKey.ts similarity index 64% rename from src/lib/gramjs/crypto/AuthKey.js rename to src/lib/gramjs/crypto/AuthKey.ts index 85d346000..8c74cb5e9 100644 --- a/src/lib/gramjs/crypto/AuthKey.js +++ b/src/lib/gramjs/crypto/AuthKey.ts @@ -1,14 +1,25 @@ -const { - sha1, - toSignedLittleBuffer, - readBufferFromBigInt, - readBigIntFromBuffer, -} = require('../Helpers'); -const BinaryReader = require('../extensions/BinaryReader'); -const { sleep } = require('../Helpers'); +import type BigInt from 'big-integer'; -class AuthKey { - constructor(value, hash) { +import { BinaryReader } from '../extensions'; + +import { + readBigIntFromBuffer, + readBufferFromBigInt, + sha1, + sleep, + toSignedLittleBuffer, +} from '../Helpers'; + +export class AuthKey { + _key?: Buffer; + + _hash?: Buffer; + + private auxHash?: BigInt.BigInteger; + + keyId?: BigInt.BigInteger; + + constructor(value?: Buffer, hash?: Buffer) { if (!hash || !value) { return; } @@ -20,7 +31,7 @@ class AuthKey { this.keyId = reader.readLong(false); } - async setKey(value) { + async setKey(value?: Buffer | AuthKey) { if (!value) { this._key = undefined; this.auxHash = undefined; @@ -59,24 +70,35 @@ class AuthKey { * Calculates the new nonce hash based on the current class fields' values * @param newNonce * @param number - * @returns {bigint} + * @returns {BigInt.BigInteger} */ - async calcNewNonceHash(newNonce, number) { - newNonce = toSignedLittleBuffer(newNonce, 32); + async calcNewNonceHash( + newNonce: BigInt.BigInteger, + number: number, + ): Promise { + if (!this.auxHash) { + throw new Error('Auth key not set'); + } + + const nonce = toSignedLittleBuffer(newNonce, 32); const n = Buffer.alloc(1); n.writeUInt8(number, 0); - const data = Buffer.concat([newNonce, - Buffer.concat([n, readBufferFromBigInt(this.auxHash, 8, true)])]); + const data = Buffer.concat([ + nonce, + Buffer.concat([n, readBufferFromBigInt(this.auxHash, 8, true)]), + ]); // Calculates the message key from the given data const shaData = (await sha1(data)).slice(4, 20); return readBigIntFromBuffer(shaData, true, true); } - equals(other) { - return other instanceof this.constructor && this._key && other.getKey() && other.getKey() - .equals(this._key); + equals(other: AuthKey) { + return ( + other instanceof this.constructor + && this._key + && Buffer.isBuffer(other.getKey()) + && other.getKey()?.equals(this._key) + ); } } - -module.exports = AuthKey; diff --git a/src/lib/gramjs/crypto/CTR.js b/src/lib/gramjs/crypto/CTR.js deleted file mode 100644 index 262b2ef3b..000000000 --- a/src/lib/gramjs/crypto/CTR.js +++ /dev/null @@ -1,17 +0,0 @@ -const crypto = require('./crypto'); - -class CTR { - constructor(key, iv) { - if (!Buffer.isBuffer(key) || !Buffer.isBuffer(iv) || iv.length !== 16) { - throw new Error('Key and iv need to be a buffer'); - } - - this.cipher = crypto.createCipheriv('AES-256-CTR', key, iv); - } - - encrypt(data) { - return Buffer.from(this.cipher.update(data)); - } -} - -module.exports = CTR; diff --git a/src/lib/gramjs/crypto/CTR.ts b/src/lib/gramjs/crypto/CTR.ts new file mode 100644 index 000000000..895195254 --- /dev/null +++ b/src/lib/gramjs/crypto/CTR.ts @@ -0,0 +1,23 @@ +import { createCipheriv, createDecipheriv, type CtrImpl } from './crypto'; + +export class CTR { + private cipher: CtrImpl; + private decipher: CtrImpl; + + constructor(key: Buffer, iv: Buffer) { + if (!Buffer.isBuffer(key) || !Buffer.isBuffer(iv) || iv.length !== 16) { + throw new Error('Key and iv need to be a buffer'); + } + + this.cipher = createCipheriv('AES-256-CTR', key, iv); + this.decipher = createDecipheriv('AES-256-CTR', key, iv); + } + + encrypt(data: Buffer) { + return Buffer.from(this.cipher.update(data)); + } + + decrypt(data: Buffer) { + return Buffer.from(this.decipher.update(data)); + } +} diff --git a/src/lib/gramjs/crypto/Factorizator.js b/src/lib/gramjs/crypto/Factorizator.ts similarity index 55% rename from src/lib/gramjs/crypto/Factorizator.js rename to src/lib/gramjs/crypto/Factorizator.ts index 10796ee97..5aeb77501 100644 --- a/src/lib/gramjs/crypto/Factorizator.js +++ b/src/lib/gramjs/crypto/Factorizator.ts @@ -1,14 +1,15 @@ -const BigInt = require('big-integer'); -const { modExp } = require('../Helpers'); +import BigInt from 'big-integer'; -class Factorizator { +import { modExp } from '../Helpers'; + +export class Factorizator { /** * Calculates the greatest common divisor * @param a {BigInteger} * @param b {BigInteger} * @returns {BigInteger} */ - static gcd(a, b) { + static gcd(a: BigInt.BigInteger, b: BigInt.BigInteger) { while (b.neq(BigInt.zero)) { const temp = b; b = a.remainder(b); @@ -22,13 +23,9 @@ class Factorizator { * @param pq {BigInteger} * @returns {{p: *, q: *}} */ - static factorize(pq) { - if (pq.remainder(2) - .equals(BigInt.zero)) { - return { - p: BigInt(2), - q: pq.divide(BigInt(2)), - }; + static factorize(pq: BigInt.BigInteger) { + if (pq.remainder(2).equals(BigInt.zero)) { + return { p: BigInt(2), q: pq.divide(BigInt(2)) }; } let y = BigInt.randBetween(BigInt(1), pq.minus(1)); const c = BigInt.randBetween(BigInt(1), pq.minus(1)); @@ -43,23 +40,17 @@ class Factorizator { while (g.eq(BigInt.one)) { x = y; - for (let i = 0; BigInt(i) - .lesser(r); i++) { - y = (modExp(y, BigInt(2), pq)).add(c) - .remainder(pq); + for (let i = 0; BigInt(i).lesser(r); i++) { + y = modExp(y, BigInt(2), pq).add(c).remainder(pq); } k = BigInt.zero; while (k.lesser(r) && g.eq(BigInt.one)) { ys = y; const condition = BigInt.min(m, r.minus(k)); - for (let i = 0; BigInt(i) - .lesser(condition); i++) { - y = (modExp(y, BigInt(2), pq)).add(c) - .remainder(pq); - q = q.multiply(x.minus(y) - .abs()) - .remainder(pq); + for (let i = 0; BigInt(i).lesser(condition); i++) { + y = modExp(y, BigInt(2), pq).add(c).remainder(pq); + q = q.multiply(x.minus(y).abs()).remainder(pq); } g = Factorizator.gcd(q, pq); k = k.add(m); @@ -69,12 +60,9 @@ class Factorizator { } if (g.eq(pq)) { - // eslint-disable-next-line no-constant-condition while (true) { - ys = (modExp(ys, BigInt(2), pq)).add(c) - .remainder(pq); - g = Factorizator.gcd(x.minus(ys) - .abs(), pq); + ys = modExp(ys, BigInt(2), pq).add(c).remainder(pq); + g = Factorizator.gcd(x.minus(ys).abs(), pq); if (g.greater(1)) { break; @@ -83,14 +71,6 @@ class Factorizator { } const p = g; q = pq.divide(g); - return p < q ? { - p, - q, - } : { - p: q, - q: p, - }; + return p < q ? { p, q } : { p: q, q: p }; } } - -module.exports = Factorizator; diff --git a/src/lib/gramjs/crypto/IGE.js b/src/lib/gramjs/crypto/IGE.js deleted file mode 100644 index 2a9707f70..000000000 --- a/src/lib/gramjs/crypto/IGE.js +++ /dev/null @@ -1,33 +0,0 @@ -const { IGE: AESIGE } = require('@cryptography/aes'); -const Helpers = require('../Helpers'); - -class IGENEW { - constructor(key, iv) { - this.ige = new AESIGE(key, iv); - } - - /** - * Decrypts the given text in 16-bytes blocks by using the given key and 32-bytes initialization vector - * @param cipherText {Buffer} - * @returns {Buffer} - */ - decryptIge(cipherText) { - return Helpers.convertToLittle(this.ige.decrypt(cipherText)); - } - - /** - * Encrypts the given text in 16-bytes blocks by using the given key and 32-bytes initialization vector - * @param plainText {Buffer} - * @returns {Buffer} - */ - encryptIge(plainText) { - const padding = plainText.length % 16; - if (padding) { - plainText = Buffer.concat([plainText, Helpers.generateRandomBytes(16 - padding)]); - } - - return Helpers.convertToLittle(this.ige.encrypt(plainText)); - } -} - -module.exports = IGENEW; diff --git a/src/lib/gramjs/crypto/IGE.ts b/src/lib/gramjs/crypto/IGE.ts new file mode 100644 index 000000000..543066d9e --- /dev/null +++ b/src/lib/gramjs/crypto/IGE.ts @@ -0,0 +1,39 @@ +import { IGE as AesIge } from '@cryptography/aes'; + +import { convertToLittle, generateRandomBytes } from '../Helpers'; + +class IGENEW { + private ige: AesIge; + + constructor(key: Buffer, iv: Buffer) { + this.ige = new AesIge(key, iv); + } + + /** + * Decrypts the given text in 16-bytes blocks by using the given key and 32-bytes initialization vector + * @param cipherText {Buffer} + * @returns {Buffer} + */ + decryptIge(cipherText: Buffer): Buffer { + return convertToLittle(this.ige.decrypt(cipherText)); + } + + /** + * Encrypts the given text in 16-bytes blocks by using the given key and 32-bytes initialization vector + * @param plainText {Buffer} + * @returns {Buffer} + */ + encryptIge(plainText: Buffer): Buffer { + const padding = plainText.length % 16; + if (padding) { + plainText = Buffer.concat([ + plainText, + generateRandomBytes(16 - padding), + ]); + } + + return convertToLittle(this.ige.encrypt(plainText)); + } +} + +export { IGENEW as IGE }; diff --git a/src/lib/gramjs/crypto/crypto.js b/src/lib/gramjs/crypto/crypto.ts similarity index 66% rename from src/lib/gramjs/crypto/crypto.js rename to src/lib/gramjs/crypto/crypto.ts index b4984fcd3..be2a639b7 100644 --- a/src/lib/gramjs/crypto/crypto.js +++ b/src/lib/gramjs/crypto/crypto.ts @@ -1,18 +1,13 @@ -const AES = require('@cryptography/aes').default; -const { - i2ab, - ab2i, -} = require('./converters'); -const { getWords } = require('./words'); +import AES from '@cryptography/aes'; + +import { ab2i, i2ab } from './converters'; +import { getWords } from './words'; class Counter { - constructor(initialValue) { - this.setBytes(initialValue); - } + _counter: Buffer; - setBytes(bytes) { - bytes = Buffer.from(bytes); - this._counter = bytes; + constructor(initialValue: Buffer) { + this._counter = Buffer.from(initialValue); } increment() { @@ -28,7 +23,15 @@ class Counter { } class CTR { - constructor(key, counter) { + private _counter: Counter; + + private _remainingCounter?: Buffer; + + private _remainingCounterIndex: number; + + private _aes: AES; + + constructor(key: Buffer, counter: Counter | Buffer) { if (!(counter instanceof Counter)) { counter = new Counter(counter); } @@ -41,11 +44,11 @@ class CTR { this._aes = new AES(getWords(key)); } - update(plainText) { + update(plainText: Buffer) { return this.encrypt(plainText); } - encrypt(plainText) { + encrypt(plainText: Buffer) { const encrypted = Buffer.from(plainText); for (let i = 0; i < encrypted.length; i++) { @@ -54,15 +57,19 @@ class CTR { this._remainingCounterIndex = 0; this._counter.increment(); } - encrypted[i] ^= this._remainingCounter[this._remainingCounterIndex++]; + if (this._remainingCounter) { + encrypted[i] ^= this._remainingCounter[this._remainingCounterIndex++]; + } } return encrypted; } } +export type CtrImpl = CTR; + // endregion -function createDecipheriv(algorithm, key, iv) { +export function createDecipheriv(algorithm: string, key: Buffer, iv: Buffer) { if (algorithm.includes('ECB')) { throw new Error('Not supported'); } else { @@ -70,7 +77,7 @@ function createDecipheriv(algorithm, key, iv) { } } -function createCipheriv(algorithm, key, iv) { +export function createCipheriv(algorithm: string, key: Buffer, iv: Buffer) { if (algorithm.includes('ECB')) { throw new Error('Not supported'); } else { @@ -78,18 +85,18 @@ function createCipheriv(algorithm, key, iv) { } } -function randomBytes(count) { +export function randomBytes(count: number) { const bytes = new Uint8Array(count); crypto.getRandomValues(bytes); return bytes; } class Hash { - constructor(algorithm) { - this.algorithm = algorithm; - } + private data = new Uint8Array(0); - update(data) { + constructor(private algorithm: 'sha1' | 'sha256') {} + + update(data: ArrayLike) { // We shouldn't be needing new Uint8Array but it doesn't // work without it this.data = new Uint8Array(data); @@ -99,15 +106,14 @@ class Hash { if (this.algorithm === 'sha1') { // eslint-disable-next-line no-restricted-globals return Buffer.from(await self.crypto.subtle.digest('SHA-1', this.data)); - } else if (this.algorithm === 'sha256') { + } else { // eslint-disable-next-line no-restricted-globals return Buffer.from(await self.crypto.subtle.digest('SHA-256', this.data)); } - return undefined; } } -async function pbkdf2(password, salt, iterations) { +export async function pbkdf2(password: Buffer, salt: Buffer, iterations: number) { const passwordKey = await crypto.subtle.importKey('raw', password, { name: 'PBKDF2' }, false, ['deriveBits']); return Buffer.from(await crypto.subtle.deriveBits({ name: 'PBKDF2', @@ -117,14 +123,6 @@ async function pbkdf2(password, salt, iterations) { }, passwordKey, 512)); } -function createHash(algorithm) { +export function createHash(algorithm: 'sha1' | 'sha256') { return new Hash(algorithm); } - -module.exports = { - createCipheriv, - createDecipheriv, - randomBytes, - createHash, - pbkdf2, -}; diff --git a/src/lib/gramjs/errors/Common.js b/src/lib/gramjs/errors/Common.ts similarity index 82% rename from src/lib/gramjs/errors/Common.js rename to src/lib/gramjs/errors/Common.ts index 95965896a..6bd24d5a9 100644 --- a/src/lib/gramjs/errors/Common.js +++ b/src/lib/gramjs/errors/Common.ts @@ -2,10 +2,12 @@ * Errors not related to the Telegram API itself */ +import type { Api } from '../tl'; + /** * Occurs when a read operation was cancelled. */ -class ReadCancelledError extends Error { +export class ReadCancelledError extends Error { constructor() { super('The read operation was cancelled.'); } @@ -15,8 +17,12 @@ class ReadCancelledError extends Error { * Occurs when a type is not found, for example, * when trying to read a TLObject with an invalid constructor code. */ -class TypeNotFoundError extends Error { - constructor(invalidConstructorId, remaining) { +export class TypeNotFoundError extends Error { + invalidConstructorId: number; + + remaining: Buffer; + + constructor(invalidConstructorId: number, remaining: Buffer) { super(`Could not find a matching Constructor ID for the TLObject that was supposed to be read with ID ${invalidConstructorId}. Most likely, a TLObject was trying to be read when it should not be read. Remaining bytes: ${remaining.length}`); @@ -33,8 +39,12 @@ class TypeNotFoundError extends Error { * Occurs when using the TCP full mode and the checksum of a received * packet doesn't match the expected checksum. */ -class InvalidChecksumError extends Error { - constructor(checksum, validChecksum) { +export class InvalidChecksumError extends Error { + checksum: number; + + validChecksum: number; + + constructor(checksum: number, validChecksum: number) { super(`Invalid checksum (${checksum} when ${validChecksum} was expected). This packet should be skipped.`); this.checksum = checksum; this.validChecksum = validChecksum; @@ -45,8 +55,12 @@ class InvalidChecksumError extends Error { * Occurs when the buffer is invalid, and may contain an HTTP error code. * For instance, 404 means "forgotten/broken authorization key", while */ -class InvalidBufferError extends Error { - constructor(payload) { +export class InvalidBufferError extends Error { + code?: number; + + payload: Buffer; + + constructor(payload: Buffer) { let code; if (payload.length === 4) { code = -payload.readInt32LE(0); @@ -62,8 +76,8 @@ class InvalidBufferError extends Error { /** * Generic security error, mostly used when generating a new AuthKey. */ -class SecurityError extends Error { - constructor(...args) { +export class SecurityError extends Error { + constructor(...args: any[]) { if (!args.length) { args = ['A security check failed.']; } @@ -75,7 +89,7 @@ class SecurityError extends Error { * Occurs when there's a hash mismatch between the decrypted CDN file * and its expected hash. */ -class CdnFileTamperedError extends SecurityError { +export class CdnFileTamperedError extends SecurityError { constructor() { super('The CDN file has been altered and its download cancelled.'); } @@ -84,8 +98,8 @@ class CdnFileTamperedError extends SecurityError { /** * Occurs when handling a badMessageNotification */ -class BadMessageError extends Error { - static ErrorMessages = { +export class BadMessageError extends Error { + static ErrorMessages: Record = { 16: 'msg_id too low (most likely, client time is wrong it would be worthwhile to ' + 'synchronize it using msg_id notifications and re-send the original message ' @@ -125,24 +139,18 @@ class BadMessageError extends Error { 64: 'Invalid container.', }; - constructor(request, code) { + code: number; + + errorMessage: string; + + constructor(request: Api.AnyRequest, code: number) { let errorMessage = BadMessageError.ErrorMessages[code] || `Unknown error code (this should not happen): ${code}.`; errorMessage += ` Caused by ${request.className}`; super(errorMessage); - this.message = errorMessage; + this.errorMessage = errorMessage; this.code = code; } } // TODO : Support multi errors. - -module.exports = { - ReadCancelledError, - TypeNotFoundError, - InvalidChecksumError, - InvalidBufferError, - SecurityError, - CdnFileTamperedError, - BadMessageError, -}; diff --git a/src/lib/gramjs/errors/RPCBaseErrors.js b/src/lib/gramjs/errors/RPCBaseErrors.ts similarity index 63% rename from src/lib/gramjs/errors/RPCBaseErrors.js rename to src/lib/gramjs/errors/RPCBaseErrors.ts index ef7edb440..ea8294f2d 100644 --- a/src/lib/gramjs/errors/RPCBaseErrors.js +++ b/src/lib/gramjs/errors/RPCBaseErrors.ts @@ -1,19 +1,25 @@ +import type { Api } from '../tl'; + /** * Base class for all Remote Procedure Call errors. */ -class RPCError extends Error { - constructor(message, request, code = undefined) { +export class RPCError extends Error { + public code: number | undefined; + + public errorMessage: string; + + constructor(message: string, request: Api.AnyRequest, code?: number) { super( 'RPCError {0}: {1}{2}' - .replace('{0}', code) + .replace('{0}', code?.toString() || '') .replace('{1}', message) .replace('{2}', RPCError._fmtRequest(request)), ); this.code = code; - this.message = message; + this.errorMessage = message; } - static _fmtRequest(request) { + static _fmtRequest(request: Api.AnyRequest) { // TODO fix this if (request) { return ` (caused by ${request.className})`; @@ -26,11 +32,11 @@ class RPCError extends Error { /** * The request must be repeated, but directed to a different data center. */ -class InvalidDCError extends RPCError { - constructor(request, message, code) { +export class InvalidDCError extends RPCError { + constructor(message: string, request: Api.AnyRequest, code?: number) { super(message, request, code); this.code = code || 303; - this.message = message || 'ERROR_SEE_OTHER'; + this.errorMessage = message || 'ERROR_SEE_OTHER'; } } @@ -39,49 +45,49 @@ class InvalidDCError extends RPCError { * using a form and contains user generated data, the user should be * notified that the data must be corrected before the query is repeated. */ -class BadRequestError extends RPCError { +export class BadRequestError extends RPCError { code = 400; - message = 'BAD_REQUEST'; + errorMessage = 'BAD_REQUEST'; } /** * There was an unauthorized attempt to use functionality available only * to authorized users. */ -class UnauthorizedError extends RPCError { +export class UnauthorizedError extends RPCError { code = 401; - message = 'UNAUTHORIZED'; + errorMessage = 'UNAUTHORIZED'; } /** * Privacy violation. For example, an attempt to write a message to * someone who has blacklisted the current user. */ -class ForbiddenError extends RPCError { +export class ForbiddenError extends RPCError { code = 403; - message = 'FORBIDDEN'; + errorMessage = 'FORBIDDEN'; } /** * An attempt to invoke a non-existent object, such as a method. */ -class NotFoundError extends RPCError { +export class NotFoundError extends RPCError { code = 404; - message = 'NOT_FOUND'; + errorMessage = 'NOT_FOUND'; } /** * Errors related to invalid authorization key, like * AUTH_KEY_DUPLICATED which can cause the connection to fail. */ -class AuthKeyError extends RPCError { +export class AuthKeyError extends RPCError { code = 406; - message = 'AUTH_KEY'; + errorMessage = 'AUTH_KEY'; } /** @@ -90,10 +96,10 @@ class AuthKeyError extends RPCError { * attempt to request a large number of text messages (SMS) for the same * phone number. */ -class FloodError extends RPCError { +export class FloodError extends RPCError { code = 420; - message = 'FLOOD'; + errorMessage = 'FLOOD'; } /** @@ -101,31 +107,18 @@ class FloodError extends RPCError { * for example, there was a disruption while accessing a database or file * storage */ -class ServerError extends RPCError { +export class ServerError extends RPCError { code = 500; // Also witnessed as -500 - message = 'INTERNAL'; + errorMessage = 'INTERNAL'; } /** * Clicking the inline buttons of bots that never (or take to long to) * call ``answerCallbackQuery`` will result in this "special" RPCError. */ -class TimedOutError extends RPCError { +export class TimedOutError extends RPCError { code = 503; // Only witnessed as -503 - message = 'Timeout'; + errorMessage = 'Timeout'; } - -module.exports = { - RPCError, - InvalidDCError, - BadRequestError, - UnauthorizedError, - ForbiddenError, - NotFoundError, - AuthKeyError, - FloodError, - ServerError, - TimedOutError, -}; diff --git a/src/lib/gramjs/errors/RPCErrorList.js b/src/lib/gramjs/errors/RPCErrorList.ts similarity index 53% rename from src/lib/gramjs/errors/RPCErrorList.js rename to src/lib/gramjs/errors/RPCErrorList.ts index a96f3d43f..94d2d63f0 100644 --- a/src/lib/gramjs/errors/RPCErrorList.js +++ b/src/lib/gramjs/errors/RPCErrorList.ts @@ -1,117 +1,154 @@ -const { - RPCError, - InvalidDCError, - FloodError, - BadRequestError, - TimedOutError, -} = require('./RPCBaseErrors'); +/* eslint-disable max-len */ +import { + BadRequestError, FloodError, InvalidDCError, RPCError, TimedOutError, +} from './RPCBaseErrors'; -class UserMigrateError extends InvalidDCError { - constructor(args) { +export class UserMigrateError extends InvalidDCError { + public newDc: number; + + constructor(args: any) { const newDc = Number(args.capture || 0); - // eslint-disable-next-line max-len - super(`The user whose identity is being used to execute queries is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`); - // eslint-disable-next-line max-len + super(`The user whose identity is being used to execute queries is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`, args.request); this.message = `The user whose identity is being used to execute queries is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`; this.newDc = newDc; } } -class PhoneMigrateError extends InvalidDCError { - constructor(args) { +export class PhoneMigrateError extends InvalidDCError { + public newDc: number; + + constructor(args: any) { const newDc = Number(args.capture || 0); - // eslint-disable-next-line max-len - super(`The phone number a user is trying to use for authorization is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`); - // eslint-disable-next-line max-len + super(`The phone number a user is trying to use for authorization is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`, args.request); this.message = `The phone number a user is trying to use for authorization is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`; this.newDc = newDc; } } -class SlowModeWaitError extends FloodError { - constructor(args) { +export class SlowModeWaitError extends FloodError { + public seconds: number; + + constructor(args: any) { const seconds = Number(args.capture || 0); - // eslint-disable-next-line max-len - super(`A wait of ${seconds} seconds is required before sending another message in this chat${RPCError._fmtRequest(args.request)}`); - // eslint-disable-next-line max-len + super( + `A wait of ${seconds} seconds is required before sending another message in this chat ${RPCError._fmtRequest(args.request)}`, + args.request, + ); this.message = `A wait of ${seconds} seconds is required before sending another message in this chat${RPCError._fmtRequest(args.request)}`; this.seconds = seconds; } } -class FloodWaitError extends FloodError { - constructor(args) { +export class FloodWaitError extends FloodError { + public seconds: number; + + constructor(args: any) { const seconds = Number(args.capture || 0); - super(`A wait of ${seconds} seconds is required${RPCError._fmtRequest(args.request)}`); + super( + `A wait of ${seconds} seconds is required${RPCError._fmtRequest(args.request)}`, + args.request, + ); this.message = `A wait of ${seconds} seconds is required${RPCError._fmtRequest(args.request)}`; this.seconds = seconds; } } -class FloodPremiumWaitError extends FloodWaitError { - constructor(args) { - const seconds = Number(args.capture || 0); - super(`A wait of ${seconds} seconds is required${RPCError._fmtRequest(args.request)}`); - this.message = `A wait of ${seconds} seconds is required${RPCError._fmtRequest(args.request)}`; - this.seconds = seconds; - } -} -class MsgWaitError extends FloodError { - constructor(args) { - super(`Message failed to be sent.${RPCError._fmtRequest(args.request)}`); - this.message = `Message failed to be sent.${RPCError._fmtRequest(args.request)}`; - } -} -class FloodTestPhoneWaitError extends FloodError { - constructor(args) { +export class FloodPremiumWaitError extends FloodWaitError { + constructor(args: any) { const seconds = Number(args.capture || 0); - super(`A wait of ${seconds} seconds is required in the test servers${RPCError._fmtRequest(args.request)}`); - // eslint-disable-next-line max-len + super(`A wait of ${seconds} seconds is required${RPCError._fmtRequest(args.request)}`); + this.message = `A wait of ${seconds} seconds is required${RPCError._fmtRequest(args.request)}`; + this.seconds = seconds; + } +} + +export class MsgWaitError extends FloodError { + constructor(args: any) { + super( + `Message failed to be sent.${RPCError._fmtRequest(args.request)}`, + args.request, + ); + this.message = `Message failed to be sent.${RPCError._fmtRequest( + args.request, + )}`; + } +} + +export class FloodTestPhoneWaitError extends FloodError { + public seconds: number; + + constructor(args: any) { + const seconds = Number(args.capture || 0); + super( + `A wait of ${seconds} seconds is required in the test servers${RPCError._fmtRequest(args.request)}`, + args.request, + ); this.message = `A wait of ${seconds} seconds is required in the test servers${RPCError._fmtRequest(args.request)}`; this.seconds = seconds; } } -class FileMigrateError extends InvalidDCError { - constructor(args) { +export class FileMigrateError extends InvalidDCError { + public newDc: number; + + constructor(args: any) { const newDc = Number(args.capture || 0); - super(`The file to be accessed is currently stored in DC ${newDc}${RPCError._fmtRequest(args.request)}`); - // eslint-disable-next-line max-len + super( + `The file to be accessed is currently stored in DC ${newDc}${RPCError._fmtRequest(args.request)}`, + args.request, + ); this.message = `The file to be accessed is currently stored in DC ${newDc}${RPCError._fmtRequest(args.request)}`; this.newDc = newDc; } } -class NetworkMigrateError extends InvalidDCError { - constructor(args) { +export class NetworkMigrateError extends InvalidDCError { + public newDc: number; + + constructor(args: any) { const newDc = Number(args.capture || 0); - super(`The source IP address is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`); + super( + `The source IP address is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`, + args.request, + ); this.message = `The source IP address is associated with DC ${newDc}${RPCError._fmtRequest(args.request)}`; this.newDc = newDc; } } -class EmailUnconfirmedError extends BadRequestError { - constructor(args) { +export class EmailUnconfirmedError extends BadRequestError { + codeLength: number; + + constructor(args: any) { const codeLength = Number(args.capture || 0); - super(`Email unconfirmed, the length of the code must be ${codeLength}${RPCError._fmtRequest(args.request)}`); + super( + `Email unconfirmed, the length of the code must be ${codeLength}${RPCError._fmtRequest( + args.request, + )}`, + args.request, + 400, + ); // eslint-disable-next-line max-len - this.message = `Email unconfirmed, the length of the code must be ${codeLength}${RPCError._fmtRequest(args.request)}`; + this.message = `Email unconfirmed, the length of the code must be ${codeLength}${RPCError._fmtRequest( + args.request, + )}`; this.codeLength = codeLength; } } -class PasswordModifiedError extends BadRequestError { - constructor(args) { +export class PasswordModifiedError extends BadRequestError { + public seconds: number; + + constructor(args: any) { const seconds = Number(args.capture || 0); - super(`The password was modified less than 24 hours ago, try again in ${seconds} seconds.`); + super(`The password was modified less than 24 hours ago, try again in ${seconds} seconds.`, args.request); // eslint-disable-next-line max-len this.message = `The password was modified less than 24 hours ago, try again in ${seconds} seconds.`; this.seconds = seconds; } } -const rpcErrorRe = [ +export const rpcErrorRe = new Map([ [/FILE_MIGRATE_(\d+)/, FileMigrateError], [/FLOOD_TEST_PHONE_WAIT_(\d+)/, FloodTestPhoneWaitError], [/FLOOD_WAIT_(\d+)/, FloodWaitError], @@ -124,18 +161,4 @@ const rpcErrorRe = [ [/EMAIL_UNCONFIRMED_(\d+)/, EmailUnconfirmedError], [/PASSWORD_TOO_FRESH_(\d+)/, PasswordModifiedError], [/^Timeout$/, TimedOutError], -]; -module.exports = { - rpcErrorRe, - FileMigrateError, - FloodTestPhoneWaitError, - FloodWaitError, - FloodPremiumWaitError, - PhoneMigrateError, - SlowModeWaitError, - UserMigrateError, - NetworkMigrateError, - MsgWaitError, - EmailUnconfirmedError, - PasswordModifiedError, -}; +]); diff --git a/src/lib/gramjs/errors/index.js b/src/lib/gramjs/errors/index.js deleted file mode 100644 index 7308fa02f..000000000 --- a/src/lib/gramjs/errors/index.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Converts a Telegram's RPC Error to a Python error. - * @param rpcError the RPCError instance - * @param request the request that caused this error - * @constructor the RPCError as a Python exception that represents this error - */ -const { RPCError } = require('./RPCBaseErrors'); -const { rpcErrorRe } = require('./RPCErrorList'); - -function RPCMessageToError(rpcError, request) { - for (const [msgRegex, Cls] of rpcErrorRe) { - const m = rpcError.errorMessage.match(msgRegex); - if (m) { - const capture = m.length === 2 ? parseInt(m[1], 10) : undefined; - return new Cls({ - request, - capture, - }); - } - } - - return new RPCError(rpcError.errorMessage, request); -} - -const Common = require('./Common'); -const RPCBaseErrors = require('./RPCBaseErrors'); -const RPCErrorList = require('./RPCErrorList'); - -module.exports = { - RPCMessageToError, - ...Common, - ...RPCBaseErrors, - ...RPCErrorList, -}; diff --git a/src/lib/gramjs/errors/index.ts b/src/lib/gramjs/errors/index.ts new file mode 100644 index 000000000..485f04ea1 --- /dev/null +++ b/src/lib/gramjs/errors/index.ts @@ -0,0 +1,28 @@ +/** + * Converts a Telegram's RPC Error to a Python error. + * @param rpcError the RPCError instance + * @param request the request that caused this error + * @constructor the RPCError as a Python exception that represents this error + */ +import type { Api } from '../tl'; + +import { RPCError } from './RPCBaseErrors'; +import { rpcErrorRe } from './RPCErrorList'; + +export function RPCMessageToError( + rpcError: Api.RpcError, + request: Api.AnyRequest, +) { + for (const [msgRegex, Cls] of rpcErrorRe) { + const m = rpcError.errorMessage.match(msgRegex); + if (m) { + const capture = m.length === 2 ? parseInt(m[1], 10) : undefined; + return new Cls({ request, capture }); + } + } + return new RPCError(rpcError.errorMessage, request, rpcError.errorCode); +} + +export * from './Common'; +export * from './RPCBaseErrors'; +export * from './RPCErrorList'; diff --git a/src/lib/gramjs/events/NewMessage.js b/src/lib/gramjs/events/NewMessage.js deleted file mode 100644 index 046b6a743..000000000 --- a/src/lib/gramjs/events/NewMessage.js +++ /dev/null @@ -1,94 +0,0 @@ -/* CONTEST -const { EventBuilder, EventCommon } = require('./common') -const { constructors } = require('../tl') - -class NewMessage extends EventBuilder { - constructor(args = { - chats: null, - func: null, - }) { - super(args) - - this.chats = args.chats - this.func = args.func - this._noCheck = true - } - - async _resolve(client) { - await super._resolve(client) - // this.fromUsers = await _intoIdSet(client, this.fromUsers) - } - - build(update, others = null, thisId = null) { - let event - if (update instanceof constructors.UpdateNewMessage || update instanceof constructors.UpdateNewChannelMessage) { - if (!(update.message instanceof constructors.Message)) { - return - } - event = new Event(update.message) - } else if (update instanceof constructors.UpdateShortMessage) { - event = new Event(new constructors.Message({ - out: update.out, - mentioned: update.mentioned, - mediaUnread: update.mediaUnread, - silent: update.silent, - id: update.id, - // Note that to_id/from_id complement each other in private - // messages, depending on whether the message was outgoing. - toId: new constructors.PeerUser(update.out ? update.userId : thisId), - fromId: update.out ? thisId : update.userId, - message: update.message, - date: update.date, - fwdFrom: update.fwdFrom, - viaBotId: update.viaBotId, - replyToMsgId: update.replyToMsgId, - entities: update.entities, - })) - } else if (update instanceof constructors.UpdateShortChatMessage) { - event = new this.Event(new constructors.Message({ - out: update.out, - mentioned: update.mentioned, - mediaUnread: update.mediaUnread, - silent: update.silent, - id: update.id, - toId: new constructors.PeerChat(update.chatId), - fromId: update.fromId, - message: update.message, - date: update.date, - fwdFrom: update.fwdFrom, - viaBotId: update.viaBotId, - replyToMsgId: update.replyToMsgId, - entities: update.entities, - })) - } else { - return - } - - // Make messages sent to ourselves outgoing unless they're forwarded. - // This makes it consistent with official client's appearance. - const ori = event.message - if (ori.toId instanceof constructors.PeerUser) { - if (ori.fromId === ori.toId.userId && !ori.fwdFrom) { - event.message.out = true - } - } - return event - } - - filter(event) { - if (this._noCheck) { - return event - } - return event - } -} - -class Event extends EventCommon { - constructor(message) { - super() - this.message = message - } -} - -module.exports = NewMessage -*/ diff --git a/src/lib/gramjs/events/Raw.js b/src/lib/gramjs/events/Raw.js deleted file mode 100644 index 0d39470e5..000000000 --- a/src/lib/gramjs/events/Raw.js +++ /dev/null @@ -1,21 +0,0 @@ -const { EventBuilder } = require('./common'); - -class Raw extends EventBuilder { - constructor(args = { - types: undefined, - func: undefined, - }) { - super(); - if (!args.types) { - this.types = true; - } else { - this.types = args.types; - } - } - - build(update) { - return update; - } -} - -module.exports = Raw; diff --git a/src/lib/gramjs/events/common.js b/src/lib/gramjs/events/common.js deleted file mode 100644 index 2e5916d65..000000000 --- a/src/lib/gramjs/events/common.js +++ /dev/null @@ -1,21 +0,0 @@ -class EventBuilder { - constructor(args = { - chats: undefined, - blacklistChats: undefined, - func: undefined, - }) { - this.chats = args.chats; - this.blacklistChats = Boolean(args.blacklistChats); - this.resolved = false; - this.func = args.func; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - build(update) { - - } -} - -module.exports = { - EventBuilder, -}; diff --git a/src/lib/gramjs/events/index.js b/src/lib/gramjs/events/index.js deleted file mode 100644 index 04a9c8c5d..000000000 --- a/src/lib/gramjs/events/index.js +++ /dev/null @@ -1,12 +0,0 @@ -const NewMessage = require('./NewMessage'); -const Raw = require('./Raw'); - -class StopPropagation extends Error { - -} - -module.exports = { - NewMessage, - StopPropagation, - Raw, -}; diff --git a/src/lib/gramjs/extensions/AsyncQueue.js b/src/lib/gramjs/extensions/AsyncQueue.ts similarity index 63% rename from src/lib/gramjs/extensions/AsyncQueue.js rename to src/lib/gramjs/extensions/AsyncQueue.ts index f88255e0e..9c7c03dc4 100644 --- a/src/lib/gramjs/extensions/AsyncQueue.js +++ b/src/lib/gramjs/extensions/AsyncQueue.ts @@ -1,13 +1,25 @@ -class AsyncQueue { +export default class AsyncQueue { + private _queue: T[]; + + private canGet: Promise; + + private resolveGet: (value: boolean) => void; + + private canPush: Promise | boolean; + + private resolvePush: (value: boolean) => void; + constructor() { this._queue = []; + this.resolvePush = () => {}; + this.resolveGet = () => {}; this.canGet = new Promise((resolve) => { this.resolveGet = resolve; }); this.canPush = true; } - async push(value) { + async push(value: T) { await this.canPush; this._queue.push(value); this.resolveGet(true); @@ -26,5 +38,3 @@ class AsyncQueue { return returned; } } - -module.exports = AsyncQueue; diff --git a/src/lib/gramjs/extensions/BinaryReader.js b/src/lib/gramjs/extensions/BinaryReader.ts similarity index 87% rename from src/lib/gramjs/extensions/BinaryReader.js rename to src/lib/gramjs/extensions/BinaryReader.ts index 99d1301f5..f063d6aef 100644 --- a/src/lib/gramjs/extensions/BinaryReader.js +++ b/src/lib/gramjs/extensions/BinaryReader.ts @@ -1,14 +1,21 @@ -const { TypeNotFoundError } = require('../errors/Common'); -const { coreObjects } = require('../tl/core'); -const { tlobjects } = require('../tl/AllTLObjects'); -const { readBigIntFromBuffer } = require('../Helpers'); +import { TypeNotFoundError } from '../errors'; +import { coreObjects } from '../tl/core'; + +import { readBigIntFromBuffer } from '../Helpers'; +import { tlobjects } from '../tl/AllTLObjects'; + +export default class BinaryReader { + private readonly stream: Buffer; + + private _last?: Buffer; + + offset: number; -class BinaryReader { /** * Small utility class to read binary data. * @param data {Buffer} */ - constructor(data) { + constructor(data: Buffer) { this.stream = data; this._last = undefined; this.offset = 0; @@ -54,8 +61,7 @@ class BinaryReader { * @returns {number} */ readFloat() { - return this.read(4) - .readFloatLE(0); + return this.read(4).readFloatLE(0); } /** @@ -64,8 +70,7 @@ class BinaryReader { */ readDouble() { // was this a bug ? it should have been { this.resolveRead = resolve; @@ -41,21 +54,21 @@ class HttpStream { return data; } - static getURL(ip: string, port: number, testServers: boolean, isPremium: boolean) { + static getURL(ip: string, port: number, isTestServer?: boolean, isPremium?: boolean) { if (port === 443) { - return `https://${ip}:${port}/apiw1${testServers ? '_test' : ''}${isPremium ? '_premium' : ''}`; + return `https://${ip}:${port}/apiw1${isTestServer ? '_test' : ''}${isPremium ? '_premium' : ''}`; } else { - return `http://${ip}:${port}/apiw1${testServers ? '_test' : ''}${isPremium ? '_premium' : ''}`; + return `http://${ip}:${port}/apiw1${isTestServer ? '_test' : ''}${isPremium ? '_premium' : ''}`; } } - async connect(port: number, ip: string, testServers = false, isPremium = false) { + async connect(port: number, ip: string, isTestServer = false, isPremium = false) { this.stream = []; this.canRead = new Promise((resolve, reject) => { this.resolveRead = resolve; this.rejectRead = reject; }); - this.url = HttpStream.getURL(ip, port, testServers, isPremium); + this.url = HttpStream.getURL(ip, port, isTestServer, isPremium); await fetch(this.url, { method: 'POST', @@ -108,5 +121,3 @@ class HttpStream { this.disconnectedCallback = undefined; } } - -export default HttpStream; diff --git a/src/lib/gramjs/extensions/Logger.js b/src/lib/gramjs/extensions/Logger.ts similarity index 64% rename from src/lib/gramjs/extensions/Logger.js rename to src/lib/gramjs/extensions/Logger.ts index 23d096558..f5b6e1785 100644 --- a/src/lib/gramjs/extensions/Logger.js +++ b/src/lib/gramjs/extensions/Logger.ts @@ -1,15 +1,23 @@ -// eslint-disable-next-line @typescript-eslint/naming-convention -let _level; +export type LoggerLevel = 'error' | 'warn' | 'info' | 'debug'; -class Logger { - static LEVEL_MAP = new Map([ +// eslint-disable-next-line @typescript-eslint/naming-convention +let _level: LoggerLevel; + +type ColorKey = LoggerLevel | 'start' | 'end'; + +export default class Logger { + static LEVEL_MAP = new Map>([ ['error', new Set(['error'])], ['warn', new Set(['error', 'warn'])], ['info', new Set(['error', 'warn', 'info'])], ['debug', new Set(['error', 'warn', 'info', 'debug'])], ]); - constructor(level) { + colors: Record; + + messageFormat: string; + + constructor(level?: LoggerLevel) { if (!_level) { _level = level || 'debug'; } @@ -25,59 +33,38 @@ class Logger { this.messageFormat = '[%t] [%l] - [%m]'; } - static setLevel(level) { + static setLevel(level: LoggerLevel) { _level = level; } - /** - * - * @param level {string} - * @returns {boolean} - */ - canSend(level) { - return Logger.LEVEL_MAP.get(_level).has(level); + canSend(level: LoggerLevel) { + if (!_level) return false; + return Logger.LEVEL_MAP.get(_level)!.has(level); } - /** - * @param message {string} - */ - warn(message) { + warn(message: string) { this._log('warn', message, this.colors.warn); } - /** - * @param message {string} - */ - info(message) { + info(message: string) { this._log('info', message, this.colors.info); } - /** - * @param message {string} - */ - debug(message) { + debug(message: string) { this._log('debug', message, this.colors.debug); } - /** - * @param message {string} - */ - error(message) { + error(message: string) { this._log('error', message, this.colors.error); } - format(message, level) { + format(message: string, level: LoggerLevel) { return this.messageFormat.replace('%t', new Date().toISOString()) .replace('%l', level.toUpperCase()) .replace('%m', message); } - /** - * @param level {string} - * @param message {string} - * @param color {string} - */ - _log(level, message, color) { + _log(level: LoggerLevel, message: string, color: string) { if (!_level) { return; } @@ -87,5 +74,3 @@ class Logger { } } } - -module.exports = Logger; diff --git a/src/lib/gramjs/extensions/MessagePacker.js b/src/lib/gramjs/extensions/MessagePacker.ts similarity index 82% rename from src/lib/gramjs/extensions/MessagePacker.js rename to src/lib/gramjs/extensions/MessagePacker.ts index 1962704b0..1af7d2e31 100644 --- a/src/lib/gramjs/extensions/MessagePacker.js +++ b/src/lib/gramjs/extensions/MessagePacker.ts @@ -1,14 +1,31 @@ -const MessageContainer = require('../tl/core/MessageContainer'); -const TLMessage = require('../tl/core/TLMessage'); -const BinaryWriter = require('./BinaryWriter'); +import type MTProtoState from '../network/MTProtoState'; +import type RequestState from '../network/RequestState'; +import type Logger from './Logger'; + +import TLMessage from '../tl/core/TLMessage'; + +import MessageContainer from '../tl/core/MessageContainer'; +import BinaryWriter from './BinaryWriter'; const USE_INVOKE_AFTER_WITH = new Set([ 'messages.SendMessage', 'messages.SendMedia', 'messages.SendMultiMedia', 'messages.ForwardMessages', 'messages.SendInlineBotResult', ]); -class MessagePacker { - constructor(state, logger) { +export default class MessagePacker { + private _state: MTProtoState; + + public _pendingStates: RequestState[]; + + private _queue: (RequestState | undefined)[]; + + private _ready: Promise; + + setReady: ((value?: any) => void) | undefined; + + private _log: Logger; + + constructor(state: MTProtoState, logger: Logger) { this._state = state; this._queue = []; this._pendingStates = []; @@ -27,14 +44,14 @@ class MessagePacker { this.append(undefined); } - append(state, setReady = true, atStart = false) { + append(state?: RequestState, setReady = true, atStart = false) { // We need to check if there is already a `USE_INVOKE_AFTER_WITH` request if (state && USE_INVOKE_AFTER_WITH.has(state.request.className)) { if (atStart) { // Assign `after` for the previously first `USE_INVOKE_AFTER_WITH` request for (let i = 0; i < this._queue.length; i++) { if (USE_INVOKE_AFTER_WITH.has(this._queue[i]?.request.className)) { - this._queue[i].after = state; + this._queue[i]!.after = state; break; } } @@ -56,7 +73,7 @@ class MessagePacker { } if (setReady) { - this.setReady(true); + this.setReady?.(true); } // 1658238041=MsgsAck, we don't care about MsgsAck here because they never resolve anyway. @@ -64,7 +81,7 @@ class MessagePacker { this._pendingStates.push(state); state.promise // Using finally causes triggering `unhandledrejection` event - .catch(() => { + ?.catch(() => { }) .finally(() => { this._pendingStates = this._pendingStates.filter((s) => s !== state); @@ -72,22 +89,22 @@ class MessagePacker { } } - prepend(states) { + prepend(states: RequestState[]) { states.reverse().forEach((state) => { this.append(state, false, true); }); - this.setReady(true); + this.setReady?.(true); } - extend(states) { + extend(states: RequestState[]) { states.forEach((state) => { this.append(state, false); }); - this.setReady(true); + this.setReady?.(true); } - async getBeacon(state) { + async getBeacon(state: RequestState) { const buffer = new BinaryWriter(Buffer.alloc(0)); const size = state.data.length + TLMessage.SIZE_OVERHEAD; if (size <= MessageContainer.MAXIMUM_SIZE) { @@ -105,7 +122,7 @@ class MessagePacker { } this._log.warn(`Message payload for ${state.request.className || state.request.constructor.name} is too long ${state.data.length} and cannot be sent`); - state.reject('Request Payload is too big'); + state.reject?.(new Error('Request Payload is too big')); return undefined; } @@ -137,7 +154,7 @@ class MessagePacker { } if (state.abortSignal?.aborted) { - state.reject(new Error('Request aborted')); + state.reject?.(new Error('Request aborted')); continue; } @@ -163,7 +180,7 @@ class MessagePacker { this._log.warn(`Message payload for ${state.request.className || state.request.constructor.name} is too long ${state.data.length} and cannot be sent`); - state.reject('Request Payload is too big'); + state.reject?.(new Error('Request Payload is too big')); size = 0; } if (!batch.length) { @@ -190,5 +207,3 @@ class MessagePacker { }; } } - -module.exports = MessagePacker; diff --git a/src/lib/gramjs/extensions/PendingState.js b/src/lib/gramjs/extensions/PendingState.ts similarity index 56% rename from src/lib/gramjs/extensions/PendingState.js rename to src/lib/gramjs/extensions/PendingState.ts index f66601f91..0d9dd4f7c 100644 --- a/src/lib/gramjs/extensions/PendingState.js +++ b/src/lib/gramjs/extensions/PendingState.ts @@ -1,17 +1,23 @@ -class PendingState { +import type BigInt from 'big-integer'; + +import type RequestState from '../network/RequestState'; + +export default class PendingState { + _pending: Map; + constructor() { this._pending = new Map(); } - set(msgId, state) { + set(msgId: BigInt.BigInteger, state: RequestState) { this._pending.set(msgId.toString(), state); } - get(msgId) { + get(msgId: BigInt.BigInteger) { return this._pending.get(msgId.toString()); } - getAndDelete(msgId) { + getAndDelete(msgId: BigInt.BigInteger) { const state = this.get(msgId); this.delete(msgId); return state; @@ -21,7 +27,7 @@ class PendingState { return Array.from(this._pending.values()); } - delete(msgId) { + delete(msgId: BigInt.BigInteger) { this._pending.delete(msgId.toString()); } @@ -29,5 +35,3 @@ class PendingState { this._pending.clear(); } } - -module.exports = PendingState; diff --git a/src/lib/gramjs/extensions/PromisedWebSockets.js b/src/lib/gramjs/extensions/PromisedWebSockets.ts similarity index 74% rename from src/lib/gramjs/extensions/PromisedWebSockets.js rename to src/lib/gramjs/extensions/PromisedWebSockets.ts index 96401f1eb..33a47d754 100644 --- a/src/lib/gramjs/extensions/PromisedWebSockets.js +++ b/src/lib/gramjs/extensions/PromisedWebSockets.ts @@ -1,4 +1,4 @@ -const { Mutex } = require('async-mutex'); +import { Mutex } from "async-mutex"; const mutex = new Mutex(); @@ -6,22 +6,32 @@ const closeError = new Error('WebSocket was closed'); const CONNECTION_TIMEOUT = 3000; const MAX_TIMEOUT = 30000; -class PromisedWebSockets { - constructor(disconnectedCallback) { - /* CONTEST - this.isBrowser = typeof process === 'undefined' || - process.type === 'renderer' || - process.browser === true || - process.__nwjs +export default class PromisedWebSockets { + private closed: boolean; - */ + private timeout: number; + + private stream: Buffer; + + private canRead?: boolean | Promise; + + private resolveRead: ((value?: any) => void) | undefined; + + private client: WebSocket | undefined; + + private website?: string; + + private disconnectedCallback: () => void; + + constructor(disconnectedCallback: () => void) { this.client = undefined; this.closed = true; + this.stream = Buffer.alloc(0); this.disconnectedCallback = disconnectedCallback; this.timeout = CONNECTION_TIMEOUT; } - async readExactly(number) { + async readExactly(number: number) { let readData = Buffer.alloc(0); // eslint-disable-next-line no-constant-condition while (true) { @@ -34,7 +44,7 @@ class PromisedWebSockets { } } - async read(number) { + async read(number: number) { if (this.closed) { throw closeError; } @@ -66,25 +76,26 @@ class PromisedWebSockets { return toReturn; } - getWebSocketLink(ip, port, testServers, isPremium) { + getWebSocketLink(ip: string, port: number, isTestServer?: boolean, isPremium?: boolean) { if (port === 443) { - return `wss://${ip}:${port}/apiws${testServers ? '_test' : ''}${isPremium ? '_premium' : ''}`; + return `wss://${ip}:${port}/apiws${isTestServer ? '_test' : ''}${isPremium ? '_premium' : ''}`; } else { - return `ws://${ip}:${port}/apiws${testServers ? '_test' : ''}${isPremium ? '_premium' : ''}`; + return `ws://${ip}:${port}/apiws${isTestServer ? '_test' : ''}${isPremium ? '_premium' : ''}`; } } - connect(port, ip, testServers = false, isPremium = false) { + connect(port: number, ip: string, isTestServer = false, isPremium = false) { this.stream = Buffer.alloc(0); this.canRead = new Promise((resolve) => { this.resolveRead = resolve; }); this.closed = false; - this.website = this.getWebSocketLink(ip, port, testServers, isPremium); + this.website = this.getWebSocketLink(ip, port, isTestServer, isPremium); this.client = new WebSocket(this.website, 'binary'); return new Promise((resolve, reject) => { + if (!this.client) return; let hasResolved = false; - let timeout; + let timeout: ReturnType | undefined; this.client.onopen = () => { this.receive(); resolve(this); @@ -105,7 +116,7 @@ class PromisedWebSockets { console.error(`Socket ${ip} closed. Code: ${code}, reason: ${reason}, was clean: ${wasClean}`); } - this.resolveRead(false); + this.resolveRead?.(false); this.closed = true; if (this.disconnectedCallback) { this.disconnectedCallback(); @@ -118,12 +129,12 @@ class PromisedWebSockets { if (hasResolved) return; reject(new Error('WebSocket connection timeout')); - this.resolveRead(false); + this.resolveRead?.(false); this.closed = true; if (this.disconnectedCallback) { this.disconnectedCallback(); } - this.client.close(); + this.client?.close(); this.timeout *= 2; this.timeout = Math.min(this.timeout, MAX_TIMEOUT); timeout = undefined; @@ -134,34 +145,33 @@ class PromisedWebSockets { // eslint-disable-next-line no-restricted-globals self.addEventListener('offline', async () => { await this.close(); - this.resolveRead(false); + this.resolveRead?.(false); }); }); } - write(data) { + write(data: Buffer) { if (this.closed) { throw closeError; } - this.client.send(data); + this.client?.send(data); } async close() { - await this.client.close(); + await this.client?.close(); this.closed = true; } receive() { + if (!this.client) return; this.client.onmessage = async (message) => { await mutex.runExclusive(async () => { const data = message.data instanceof ArrayBuffer ? Buffer.from(message.data) : Buffer.from(await new Response(message.data).arrayBuffer()); this.stream = Buffer.concat([this.stream, data]); - this.resolveRead(true); + this.resolveRead?.(true); }); }; } } - -module.exports = PromisedWebSockets; diff --git a/src/lib/gramjs/extensions/index.js b/src/lib/gramjs/extensions/index.js deleted file mode 100644 index b2f4c061e..000000000 --- a/src/lib/gramjs/extensions/index.js +++ /dev/null @@ -1,15 +0,0 @@ -const Logger = require('./Logger'); -const BinaryWriter = require('./BinaryWriter'); -const BinaryReader = require('./BinaryReader'); -const PromisedWebSockets = require('./PromisedWebSockets'); -const MessagePacker = require('./MessagePacker'); -const AsyncQueue = require('./AsyncQueue'); - -module.exports = { - BinaryWriter, - BinaryReader, - MessagePacker, - AsyncQueue, - Logger, - PromisedWebSockets, -}; diff --git a/src/lib/gramjs/extensions/index.ts b/src/lib/gramjs/extensions/index.ts new file mode 100644 index 000000000..ac5d5b0f3 --- /dev/null +++ b/src/lib/gramjs/extensions/index.ts @@ -0,0 +1,19 @@ +import AsyncQueue from './AsyncQueue'; +import BinaryReader from './BinaryReader'; +import BinaryWriter from './BinaryWriter'; +import HttpStream from './HttpStream'; +import Logger from './Logger'; +import MessagePacker from './MessagePacker'; +import PendingState from './PendingState'; +import PromisedWebSockets from './PromisedWebSockets'; + +export { + AsyncQueue, + BinaryReader, + BinaryWriter, + HttpStream, + Logger, + MessagePacker, + PendingState, + PromisedWebSockets, +}; diff --git a/src/lib/gramjs/index.js b/src/lib/gramjs/index.js deleted file mode 100644 index ee11b1bc9..000000000 --- a/src/lib/gramjs/index.js +++ /dev/null @@ -1,25 +0,0 @@ -const Api = require('./tl/api'); -const TelegramClient = require('./client/TelegramClient'); -const connection = require('./network'); -const tl = require('./tl'); -const version = require('./Version'); -const events = require('./events'); -const utils = require('./Utils'); -const errors = require('./errors'); -const sessions = require('./sessions'); -const extensions = require('./extensions'); -const helpers = require('./Helpers'); - -module.exports = { - Api, - TelegramClient, - sessions, - connection, - extensions, - tl, - version, - events, - utils, - errors, - helpers, -}; diff --git a/src/lib/gramjs/index.ts b/src/lib/gramjs/index.ts new file mode 100644 index 000000000..f68825dad --- /dev/null +++ b/src/lib/gramjs/index.ts @@ -0,0 +1,19 @@ +export { Api } from './tl'; +export * as errors from './errors'; +export * as extensions from './extensions'; +export * as connection from './network'; +export * as sessions from './sessions'; +export * as tl from './tl'; + +import TelegramClient, { Update, SizeType } from './client/TelegramClient'; +export * as helpers from './Helpers'; +export * as utils from './Utils'; + +export { + TelegramClient, +}; + +export type { + Update, + SizeType, +} diff --git a/src/lib/gramjs/network/Authenticator.ts b/src/lib/gramjs/network/Authenticator.ts index de04c3f41..c4ec0180f 100644 --- a/src/lib/gramjs/network/Authenticator.ts +++ b/src/lib/gramjs/network/Authenticator.ts @@ -4,27 +4,39 @@ * @param log * @returns {Promise<{authKey: *, timeOffset: *}>} */ -// eslint-disable-next-line import/no-named-default -import { default as Api } from '../tl/api'; -import { SecurityError } from '../errors'; -// eslint-disable-next-line import/no-named-default -import type { default as MTProtoPlainSender } from './MTProtoPlainSender'; -import { SERVER_KEYS } from '../crypto/RSA'; -const bigInt = require('big-integer'); -const IGE = require('../crypto/IGE'); -const AuthKey = require('../crypto/AuthKey'); -const Factorizator = require('../crypto/Factorizator'); -const Helpers = require('../Helpers'); -const BinaryReader = require('../extensions/BinaryReader'); +import bigInt from 'big-integer'; + +import type MTProtoPlainSender from './MTProtoPlainSender'; + +import { IGE } from '../crypto/IGE'; +import { SERVER_KEYS } from '../crypto/RSA'; +import { SecurityError } from '../errors'; +import { BinaryReader } from '../extensions'; +import { Api } from '../tl'; + +import { AuthKey } from '../crypto/AuthKey'; +import { Factorizator } from '../crypto/Factorizator'; +import { + bufferXor, + generateKeyDataFromNonce, + generateRandomBytes, + getByteArray, + modExp, + readBigIntFromBuffer, + readBufferFromBigInt, + sha1, + sha256, + toSignedLittleBuffer, +} from '../Helpers'; const RETRIES = 20; export async function doAuthentication(sender: MTProtoPlainSender, log: any) { // Step 1 sending: PQ Request, endianness doesn't matter since it's random - let bytes = Helpers.generateRandomBytes(16); + let bytes = generateRandomBytes(16); - const nonce = Helpers.readBigIntFromBuffer(bytes, false, true); + const nonce = readBigIntFromBuffer(bytes, false, true); const resPQ = await sender.send(new Api.ReqPqMulti({ nonce })); log.debug('Starting authKey generation step 1'); @@ -34,18 +46,18 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) { if (resPQ.nonce.neq(nonce)) { throw new SecurityError('Step 1 invalid nonce from server'); } - const pq = Helpers.readBigIntFromBuffer(resPQ.pq, false, true); + const pq = readBigIntFromBuffer(resPQ.pq, false, true); log.debug('Finished authKey generation step 1'); // Step 2 sending: DH Exchange const { p, q } = Factorizator.factorize(pq); - const pBuffer = Helpers.getByteArray(p); - const qBuffer = Helpers.getByteArray(q); + const pBuffer = getByteArray(p); + const qBuffer = getByteArray(q); - bytes = Helpers.generateRandomBytes(32); - const newNonce = Helpers.readBigIntFromBuffer(bytes, true, true); + bytes = generateRandomBytes(32); + const newNonce = readBigIntFromBuffer(bytes, true, true); const pqInnerData = new Api.PQInnerData({ - pq: Helpers.getByteArray(pq), // unsigned + pq: getByteArray(pq), // unsigned p: pBuffer, q: qBuffer, nonce: resPQ.nonce, @@ -70,28 +82,28 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) { ); } // Value should be padded to be made 192 exactly - const padding = Helpers.generateRandomBytes(192 - pqInnerData.length); + const padding = generateRandomBytes(192 - pqInnerData.length); const dataWithPadding = Buffer.concat([pqInnerData, padding]); const dataPadReversed = Buffer.from(dataWithPadding).reverse(); let encryptedData; for (let i = 0; i < RETRIES; i++) { - const tempKey = Helpers.generateRandomBytes(32); - const shaDigestKeyWithData = await Helpers.sha256(Buffer.concat([tempKey, dataWithPadding])); + const tempKey = generateRandomBytes(32); + const shaDigestKeyWithData = await sha256(Buffer.concat([tempKey, dataWithPadding])); const dataWithHash = Buffer.concat([dataPadReversed, shaDigestKeyWithData]); const ige = new IGE(tempKey, Buffer.alloc(32)); const aesEncrypted = ige.encryptIge(dataWithHash); - const tempKeyXor = Helpers.bufferXor(tempKey, await Helpers.sha256(aesEncrypted)); + const tempKeyXor = bufferXor(tempKey, await sha256(aesEncrypted)); const keyAesEncrypted = Buffer.concat([tempKeyXor, aesEncrypted]); - const keyAesEncryptedInt = Helpers.readBigIntFromBuffer(keyAesEncrypted, false, false); + const keyAesEncryptedInt = readBigIntFromBuffer(keyAesEncrypted, false, false); if (keyAesEncryptedInt.greaterOrEquals(targetKey.n)) { log.debug('Aes key greater than RSA. retrying'); continue; } - const encryptedDataBuffer = Helpers.modExp(keyAesEncryptedInt, bigInt(targetKey.e), targetKey.n); - encryptedData = Helpers.readBufferFromBigInt(encryptedDataBuffer, 256, false, false); + const encryptedDataBuffer = modExp(keyAesEncryptedInt, bigInt(targetKey.e), targetKey.n); + encryptedData = readBufferFromBigInt(encryptedDataBuffer, 256, false, false); break; } @@ -130,10 +142,10 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) { } if (serverDhParams instanceof Api.ServerDHParamsFail) { - const sh = await Helpers.sha1( - Helpers.toSignedLittleBuffer(newNonce, 32).slice(4, 20), + const sh = await sha1( + toSignedLittleBuffer(newNonce, 32).slice(4, 20), ); - const nnh = Helpers.readBigIntFromBuffer(sh, true, true); + const nnh = readBigIntFromBuffer(sh, true, true); if (serverDhParams.newNonceHash.neq(nnh)) { throw new SecurityError('Step 2 invalid DH fail nonce from server'); } @@ -145,7 +157,7 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) { log.debug('Starting authKey generation step 3'); // Step 3 sending: Complete DH Exchange - const { key, iv } = await Helpers.generateKeyDataFromNonce( + const { key, iv } = await generateKeyDataFromNonce( resPQ.serverNonce, newNonce, ); @@ -161,7 +173,7 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) { if (!(serverDhInner instanceof Api.ServerDHInnerData)) { throw new Error(`Step 3 answer was ${serverDhInner}`); } - const sha1Answer = await Helpers.sha1(serverDhInner.getBytes()); + const sha1Answer = await sha1(serverDhInner.getBytes()); if (!(hash.equals(sha1Answer))) { throw new SecurityError('Step 3 Invalid hash answer'); } @@ -183,20 +195,20 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) { throw new SecurityError('Step 3 invalid dhPrime or g'); } - const dhPrime = Helpers.readBigIntFromBuffer( + const dhPrime = readBigIntFromBuffer( serverDhInner.dhPrime, false, false, ); - const ga = Helpers.readBigIntFromBuffer(serverDhInner.gA, false, false); + const ga = readBigIntFromBuffer(serverDhInner.gA, false, false); const timeOffset = serverDhInner.serverTime - Math.floor(Date.now() / 1000); - const b = Helpers.readBigIntFromBuffer( - Helpers.generateRandomBytes(256), + const b = readBigIntFromBuffer( + generateRandomBytes(256), false, false, ); - const gb = Helpers.modExp(bigInt(serverDhInner.g), b, dhPrime); - const gab = Helpers.modExp(ga, b, dhPrime); + const gb = modExp(bigInt(serverDhInner.g), b, dhPrime); + const gab = modExp(ga, b, dhPrime); if (ga.lesserOrEquals(1)) { throw new SecurityError('Step 3 failed ga > 1 check'); @@ -223,11 +235,11 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) { nonce: resPQ.nonce, serverNonce: resPQ.serverNonce, retryId: bigInt.zero, // TODO Actual retry ID - gB: Helpers.getByteArray(gb, false), + gB: getByteArray(gb, false), }).getBytes(); const clientDdhInnerHashed = Buffer.concat([ - await Helpers.sha1(clientDhInner), + await sha1(clientDhInner), clientDhInner, ]); // Encryption @@ -262,7 +274,7 @@ export async function doAuthentication(sender: MTProtoPlainSender, log: any) { ); } const authKey = new AuthKey(); - await authKey.setKey(Helpers.getByteArray(gab)); + await authKey.setKey(getByteArray(gab)); const nonceNumber = 1 + nonceTypesString.indexOf(dhGen.className); diff --git a/src/lib/gramjs/network/MTProtoPlainSender.js b/src/lib/gramjs/network/MTProtoPlainSender.ts similarity index 76% rename from src/lib/gramjs/network/MTProtoPlainSender.js rename to src/lib/gramjs/network/MTProtoPlainSender.ts index 361746efd..e54352f82 100644 --- a/src/lib/gramjs/network/MTProtoPlainSender.js +++ b/src/lib/gramjs/network/MTProtoPlainSender.ts @@ -2,24 +2,34 @@ * This module contains the class used to communicate with Telegram's servers * in plain text, when no authorization key has been created yet. */ -const BigInt = require('big-integer'); -const MTProtoState = require('./MTProtoState'); -const BinaryReader = require('../extensions/BinaryReader'); -const { InvalidBufferError } = require('../errors/Common'); -const { toSignedLittleBuffer } = require('../Helpers'); +import BigInt from 'big-integer'; + +import type { Logger } from '../extensions'; +import type { Api } from '../tl'; +import type { Connection } from './connection'; + +import { BinaryReader } from '../extensions'; + +import { InvalidBufferError } from '../errors/Common'; +import { toSignedLittleBuffer } from '../Helpers'; +import MTProtoState from './MTProtoState'; /** * MTProto Mobile Protocol plain sender (https://core.telegram.org/mtproto/description#unencrypted-messages) */ -class MTProtoPlainSender { +export default class MTProtoPlainSender { + private _state: MTProtoState; + + private _connection: Connection; + /** * Initializes the MTProto plain sender. * @param connection connection: the Connection to be used. * @param loggers */ - constructor(connection, loggers) { - this._state = new MTProtoState(connection, loggers); + constructor(connection: Connection, loggers: Logger) { + this._state = new MTProtoState(undefined, loggers); this._connection = connection; } @@ -27,7 +37,7 @@ class MTProtoPlainSender { * Sends and receives the result for the given request. * @param request */ - async send(request) { + async send(request: Api.AnyRequest) { let body = request.getBytes(); let msgId = this._state._getNewMsgId(); const m = toSignedLittleBuffer(msgId, 8); @@ -68,5 +78,3 @@ class MTProtoPlainSender { return reader.tgReadObject(); } } - -module.exports = MTProtoPlainSender; diff --git a/src/lib/gramjs/network/MTProtoSender.js b/src/lib/gramjs/network/MTProtoSender.ts similarity index 70% rename from src/lib/gramjs/network/MTProtoSender.js rename to src/lib/gramjs/network/MTProtoSender.ts index 13372f7b7..822a7f64d 100644 --- a/src/lib/gramjs/network/MTProtoSender.js +++ b/src/lib/gramjs/network/MTProtoSender.ts @@ -1,50 +1,56 @@ -const { RPCError } = require('../errors'); +import type BigInt from 'big-integer'; -const MtProtoPlainSender = require('./MTProtoPlainSender'); -const MTProtoState = require('./MTProtoState'); -const Helpers = require('../Helpers'); -const AuthKey = require('../crypto/AuthKey'); -const { doAuthentication } = require('./Authenticator'); -const RPCResult = require('../tl/core/RPCResult'); -const MessageContainer = require('../tl/core/MessageContainer'); -const GZIPPacked = require('../tl/core/GZIPPacked'); -const RequestState = require('./RequestState'); +import type { TLMessage } from '../tl/core'; +import { type Connection, HttpConnection } from './connection'; -const { - MsgsAck, - upload, - MsgsStateInfo, - Pong, -} = require('../tl').constructors; -const MessagePacker = require('../extensions/MessagePacker'); -const BinaryReader = require('../extensions/BinaryReader'); -const PendingState = require('../extensions/PendingState'); -const { - UpdateConnectionState, - UpdateServerTimeOffset, -} = require('./updates'); -const { BadMessageError } = require('../errors/Common'); -const { - BadServerSalt, - BadMsgNotification, - MsgDetailedInfo, - MsgNewDetailedInfo, - NewSessionCreated, - FutureSalts, - MsgsStateReq, - MsgResendReq, - MsgsAllInfo, - HttpWait, -} = require('../tl').constructors; -const { SecurityError } = require('../errors/Common'); -const { InvalidBufferError } = require('../errors/Common'); -const { RPCMessageToError } = require('../errors'); -const { TypeNotFoundError } = require('../errors/Common'); +import { RPCError, RPCMessageToError } from '../errors'; +import { + BinaryReader, type Logger, MessagePacker, +} from '../extensions'; +import { Api } from '../tl'; +import GZIPPacked from '../tl/core/GZIPPacked'; +import RPCResult from '../tl/core/RPCResult'; +import { UpdateConnectionState, UpdateServerTimeOffset } from './updates'; + +import { AuthKey } from '../crypto/AuthKey'; +import { + BadMessageError, InvalidBufferError, SecurityError, TypeNotFoundError, +} from '../errors/Common'; +import PendingState from '../extensions/PendingState'; +import { sleep } from '../Helpers'; +import MessageContainer from '../tl/core/MessageContainer'; +import { doAuthentication } from './Authenticator'; +import MtProtoPlainSender from './MTProtoPlainSender'; +import MTProtoState from './MTProtoState'; +import RequestState, { CallableRequest } from './RequestState'; +import { Update } from '../client/TelegramClient'; const LONGPOLL_MAX_WAIT = 3000; const LONGPOLL_MAX_DELAY = 500; const LONGPOLL_WAIT_AFTER = 150; +interface DefaultOptions { + logger: Logger; + retries: number; + retriesToFallback: number; + retryMainConnectionDelay: number; + delay: number; + dcId: number; + senderIndex?: number; + autoReconnect: boolean; + shouldForceHttpTransport: boolean; + shouldAllowHttpTransport: boolean; + connectTimeout: number; + authKeyCallback: any; + updateCallback?: any; + autoReconnectCallback?: any; + isMainSender?: boolean; + isExported?: boolean; + senderCallback?: any; + onConnectionBreak?: CallableFunction; + getShouldDebugExportedSenders?: () => boolean; +} + /** * MTProto Mobile Protocol sender * (https://core.telegram.org/mtproto/description) @@ -58,8 +64,8 @@ const LONGPOLL_WAIT_AFTER = 150; * A new authorization key will be generated on connection if no other * key exists yet. */ -class MTProtoSender { - static DEFAULT_OPTIONS = { +export default class MTProtoSender { + static DEFAULT_OPTIONS: Partial = { logger: undefined, retries: Infinity, retriesToFallback: 1, @@ -78,11 +84,89 @@ class MTProtoSender { getShouldDebugExportedSenders: undefined, }; + _connection?: Connection; + + _fallbackConnection?: Connection; + + private _shouldForceHttpTransport: boolean; + + private _shouldAllowHttpTransport: boolean; + + private _retriesToFallback: number; + + private readonly _log: Logger; + + _dcId: number; + + _senderIndex: number; + + private readonly _retries: number; + + private readonly _delay: number; + + private _retryMainConnectionDelay: number; + + private _isFallback: boolean; + + private readonly _authKeyCallback: any; + + public _updateCallback: ( + update: Update, + ) => void; + + private readonly _autoReconnectCallback?: any; + + private readonly _isMainSender: boolean; + + private readonly _isExported: boolean; + + private _sendQueue: MessagePacker; + + private _sendQueueLongPoll: MessagePacker; + + private isSendingLongPoll?: boolean; + + private readonly _pendingAck: Set; + + private readonly _lastAcks: any[]; + + _pendingState: PendingState; + + _userConnected: boolean; + + isReconnecting: boolean; + + _disconnected: boolean; + + private _sendLoopHandle: any; + + private _recvLoopHandle: any; + + private _longPollLoopHandle: any; + + private _isReconnectingToMain = false; + + readonly authKey: AuthKey; + + private readonly _state: MTProtoState; + + _getShouldDebugExportedSenders?: () => boolean; + + private readonly _handlers: Record void>; + + private readonly _onConnectionBreak?: CallableFunction; + + userDisconnected: boolean; + + isConnecting = false; + + _authenticated = false; + /** * @param authKey * @param opts */ - constructor(authKey, opts) { + constructor(authKey: AuthKey, opts: DefaultOptions) { const args = { ...MTProtoSender.DEFAULT_OPTIONS, ...opts }; this._connection = undefined; this._fallbackConnection = undefined; @@ -90,18 +174,16 @@ class MTProtoSender { this._shouldAllowHttpTransport = args.shouldAllowHttpTransport; this._log = args.logger; this._dcId = args.dcId; - this._senderIndex = args.senderIndex; + this._senderIndex = args.senderIndex || 0; this._retries = args.retries; this._retriesToFallback = args.retriesToFallback; this._delay = args.delay; this._retryMainConnectionDelay = args.retryMainConnectionDelay; - this._autoReconnect = args.autoReconnect; - this._connectTimeout = args.connectTimeout; this._authKeyCallback = args.authKeyCallback; this._updateCallback = args.updateCallback; this._autoReconnectCallback = args.autoReconnectCallback; - this._isMainSender = args.isMainSender; - this._isExported = args.isExported; + this._isMainSender = Boolean(args.isMainSender); + this._isExported = Boolean(args.isExported); this._onConnectionBreak = args.onConnectionBreak; this._isFallback = false; this._getShouldDebugExportedSenders = args.getShouldDebugExportedSenders; @@ -119,16 +201,16 @@ class MTProtoSender { * be cleared but on explicit user disconnection all the * pending futures should be cancelled. */ - this._user_connected = false; + this._userConnected = false; this.isReconnecting = false; this._disconnected = true; /** * We need to join the loops upon disconnection */ - this._send_loop_handle = undefined; - this._long_poll_loop_handle = undefined; - this._recv_loop_handle = undefined; + this._sendLoopHandle = undefined; + this._longPollLoopHandle = undefined; + this._recvLoopHandle = undefined; /** * Preserving the references of the AuthKey and state is important @@ -140,25 +222,25 @@ class MTProtoSender { * Outgoing messages are put in a queue and sent in a batch. * Note that here we're also storing their ``_RequestState``. */ - this._send_queue = new MessagePacker(this._state, this._log); - this._send_queue_long_poll = new MessagePacker(this._state, this._log); + this._sendQueue = new MessagePacker(this._state, this._log); + this._sendQueueLongPoll = new MessagePacker(this._state, this._log); /** * Sent states are remembered until a response is received. */ - this._pending_state = new PendingState(); + this._pendingState = new PendingState(); /** * Responses must be acknowledged, and we can also batch these. */ - this._pending_ack = new Set(); + this._pendingAck = new Set(); /** * Similar to pending_messages but only for the last acknowledges. * These can't go in pending_messages because no acknowledge for them * is received, but we may still need to resend their state on bad salts. */ - this._last_acks = []; + this._lastAcks = []; /** * Jump table from response ID to method that handles it @@ -168,24 +250,24 @@ class MTProtoSender { [RPCResult.CONSTRUCTOR_ID]: this._handleRPCResult.bind(this), [MessageContainer.CONSTRUCTOR_ID]: this._handleContainer.bind(this), [GZIPPacked.CONSTRUCTOR_ID]: this._handleGzipPacked.bind(this), - [Pong.CONSTRUCTOR_ID]: this._handlePong.bind(this), - [BadServerSalt.CONSTRUCTOR_ID]: this._handleBadServerSalt.bind(this), - [BadMsgNotification.CONSTRUCTOR_ID]: this._handleBadNotification.bind(this), - [MsgDetailedInfo.CONSTRUCTOR_ID]: this._handleDetailedInfo.bind(this), - [MsgNewDetailedInfo.CONSTRUCTOR_ID]: this._handleNewDetailedInfo.bind(this), - [NewSessionCreated.CONSTRUCTOR_ID]: this._handleNewSessionCreated.bind(this), - [MsgsAck.CONSTRUCTOR_ID]: this._handleAck.bind(this), - [FutureSalts.CONSTRUCTOR_ID]: this._handleFutureSalts.bind(this), - [MsgsStateReq.CONSTRUCTOR_ID]: this._handleStateForgotten.bind(this), - [MsgResendReq.CONSTRUCTOR_ID]: this._handleStateForgotten.bind(this), - [MsgsAllInfo.CONSTRUCTOR_ID]: this._handleMsgAll.bind(this), + [Api.Pong.CONSTRUCTOR_ID]: this._handlePong.bind(this), + [Api.BadServerSalt.CONSTRUCTOR_ID]: this._handleBadServerSalt.bind(this), + [Api.BadMsgNotification.CONSTRUCTOR_ID]: this._handleBadNotification.bind(this), + [Api.MsgDetailedInfo.CONSTRUCTOR_ID]: this._handleDetailedInfo.bind(this), + [Api.MsgNewDetailedInfo.CONSTRUCTOR_ID]: this._handleNewDetailedInfo.bind(this), + [Api.NewSessionCreated.CONSTRUCTOR_ID]: this._handleNewSessionCreated.bind(this), + [Api.MsgsAck.CONSTRUCTOR_ID]: this._handleAck.bind(this), + [Api.FutureSalts.CONSTRUCTOR_ID]: this._handleFutureSalts.bind(this), + [Api.MsgsStateReq.CONSTRUCTOR_ID]: this._handleStateForgotten.bind(this), + [Api.MsgResendReq.CONSTRUCTOR_ID]: this._handleStateForgotten.bind(this), + [Api.MsgsAllInfo.CONSTRUCTOR_ID]: this._handleMsgAll.bind(this), }; } // Public API - logWithIndexCallback(level) { - return (...args) => { + logWithIndexCallback(level: 'debug' | 'log' | 'warn' | 'error') { + return (...args: unknown[]) => { if (!this._getShouldDebugExportedSenders || !this._getShouldDebugExportedSenders()) return; // eslint-disable-next-line no-console @@ -200,7 +282,7 @@ class MTProtoSender { error: this.logWithIndexCallback('error'), }; - getConnection() { + getConnection(): Connection | undefined { return this._isFallback ? this._fallbackConnection : this._connection; } @@ -211,10 +293,10 @@ class MTProtoSender { * @param fallbackConnection * @returns {Promise} */ - async connect(connection, force, fallbackConnection) { + async connect(connection: Connection, force: boolean, fallbackConnection?: Connection) { this.userDisconnected = false; - if (this._user_connected && !force) { + if (this._userConnected && !force) { this._log.info('User is already connected!'); return false; } @@ -231,7 +313,7 @@ class MTProtoSender { this._log.warn('Using fallback connection'); } this.logWithIndex.warn('Connecting...'); - await this._connect(this.getConnection()); + await this._connect(this.getConnection()!); this.logWithIndex.warn('Connected!'); if (!this._isExported) { this._updateCallback?.(new UpdateConnectionState(UpdateConnectionState.connected)); @@ -244,7 +326,7 @@ class MTProtoSender { this._log.error(`${this._isFallback ? 'HTTP' : 'WebSocket'} connection failed attempt: ${attempt + 1}`); // eslint-disable-next-line no-console console.error(err); - await Helpers.sleep(this._delay); + await sleep(this._delay); } } this.isConnecting = false; @@ -262,12 +344,12 @@ class MTProtoSender { this._log.debug('Trying to reconnect to main connection'); this._isReconnectingToMain = true; try { - await this._connection.connect(); + await this._connection!.connect(); this._log.info('Reconnected to main connection'); this.logWithIndex.warn('Reconnected to main connection'); this.isReconnecting = true; - await this._disconnect(this._fallbackConnection); - await this.connect(this._connection, true, this._fallbackConnection); + if (this._fallbackConnection) await this._disconnect(this._fallbackConnection); + await this.connect(this._connection!, true, this._fallbackConnection); this.isReconnecting = false; this._isReconnectingToMain = false; } catch (e) { @@ -276,16 +358,16 @@ class MTProtoSender { this._log.error( `Failed to reconnect to main connection, retrying in ${this._retryMainConnectionDelay}ms`, ); - await Helpers.sleep(this._retryMainConnectionDelay); + await sleep(this._retryMainConnectionDelay); void this.tryReconnectToMain(); } } else { - await Helpers.sleep(this._retryMainConnectionDelay); + await sleep(this._retryMainConnectionDelay); } } isConnected() { - return this._user_connected; + return this._userConnected; } /** @@ -295,11 +377,13 @@ class MTProtoSender { async disconnect() { this.userDisconnected = true; this.logWithIndex.warn('Disconnecting...'); - await this._disconnect(this.getConnection()); + const connection = this.getConnection(); + if (!connection) return; + await this._disconnect(connection); } destroy() { - this._send_queue.clear(); + this._sendQueue.clear(); } /** @@ -329,27 +413,28 @@ class MTProtoSender { * @param isLongPoll * @returns {RequestState} */ - send(request, abortSignal, isLongPoll = false) { - const state = new RequestState(request, abortSignal); + send(request: T, abortSignal?: AbortSignal, isLongPoll = false) { + const state = new RequestState(request, abortSignal); if (!isLongPoll) { this.logWithIndex.debug(`Send ${request.className}`); - this._send_queue.append(state); + this._sendQueue.append(state); } else { - this._send_queue_long_poll.append(state); + this._sendQueueLongPoll.append(state); } return state.promise; } - addStateToQueue(state) { - this._send_queue.append(state); + addStateToQueue(state: RequestState) { + this._sendQueue.append(state); } - async sendBeacon(request) { - if (!this._user_connected) { + async sendBeacon(request: CallableRequest) { + if (!this._userConnected || !(this._fallbackConnection instanceof HttpConnection)) { throw new Error('Cannot send requests while disconnected'); } const state = new RequestState(request, undefined); - const data = await this._send_queue.getBeacon(state); + const data = await this._sendQueue.getBeacon(state); + if (!data) return; const encryptedData = await this._state.encryptMessageData(data); postMessage({ @@ -366,9 +451,9 @@ class MTProtoSender { * @returns {Promise} * @private */ - async _connect(connection) { + async _connect(connection: Connection) { if (!connection.isConnected()) { - this._log.info('Connecting to {0}...'.replace('{0}', connection)); + this._log.info('Connecting to {0}...'.replace('{0}', connection._ip)); await connection.connect(); this._log.debug('Connection success!'); } @@ -399,22 +484,22 @@ class MTProtoSender { this._authenticated = true; this._log.debug('Already have an auth key ...'); } - this._user_connected = true; + this._userConnected = true; this.isReconnecting = false; - if (!this._send_loop_handle) { + if (!this._sendLoopHandle) { this._log.debug('Starting send loop'); - this._send_loop_handle = this._sendLoop(); + this._sendLoopHandle = this._sendLoop(); } - if (!this._recv_loop_handle) { + if (!this._recvLoopHandle) { this._log.debug('Starting receive loop'); - this._recv_loop_handle = this._recvLoop(); + this._recvLoopHandle = this._recvLoop(); } - if (!this._long_poll_loop_handle && connection.shouldLongPoll) { + if (!this._longPollLoopHandle && connection.shouldLongPoll) { this._log.debug('Starting long-poll loop'); - this._long_poll_loop_handle = this._longPollLoop(); + this._longPollLoopHandle = this._longPollLoop(); } // _disconnected only completes after manual disconnection @@ -424,7 +509,7 @@ class MTProtoSender { this._log.info('Connection to %s complete!'.replace('%s', connection.toString())); } - async _disconnect(connection) { + async _disconnect(connection: Connection) { if (!this._isExported) { this._updateCallback?.(new UpdateConnectionState(UpdateConnectionState.disconnected)); } @@ -435,21 +520,21 @@ class MTProtoSender { } this._log.info('Disconnecting from %s...'.replace('%s', connection.toString())); - this._user_connected = false; + this._userConnected = false; this._log.debug('Closing current connection...'); this.logWithIndex.warn('Disconnecting'); await connection.disconnect(); } async _longPollLoop() { - while (this._user_connected && !this.isReconnecting && this._isFallback - && this.getConnection().shouldLongPoll) { - await this._send_queue_long_poll.wait(); + while (this._userConnected && !this.isReconnecting && this._isFallback + && this.getConnection()!.shouldLongPoll) { + await this._sendQueueLongPoll.wait(); - const res = await this._send_queue_long_poll.get(); + const res = await this._sendQueueLongPoll.get(); if (this.isReconnecting || !this._isFallback) { - this._long_poll_loop_handle = undefined; + this._longPollLoopHandle = undefined; return; } @@ -463,11 +548,11 @@ class MTProtoSender { data = await this._state.encryptMessageData(data); try { - await this._fallbackConnection.send(data); - } catch (e) { + await this._fallbackConnection?.send(data); + } catch (e: any) { this._log.error(e); this._log.info('Connection closed while sending data'); - this._long_poll_loop_handle = undefined; + this._longPollLoopHandle = undefined; this.isSendingLongPoll = false; if (!this.userDisconnected) { this.reconnect(); @@ -479,7 +564,7 @@ class MTProtoSender { this.checkLongPoll(); } - this._long_poll_loop_handle = undefined; + this._longPollLoopHandle = undefined; } /** @@ -491,19 +576,19 @@ class MTProtoSender { */ async _sendLoop() { // Retry previous pending requests - this._send_queue.prepend(this._pending_state.values()); - this._pending_state.clear(); + this._sendQueue.prepend(this._pendingState.values()); + this._pendingState.clear(); - while (this._user_connected && !this.isReconnecting) { + while (this._userConnected && !this.isReconnecting) { const appendAcks = () => { - if (this._pending_ack.size) { - const ack = new RequestState(new MsgsAck({ msgIds: Array(...this._pending_ack) })); - this._send_queue.append(ack); - this._last_acks.push(ack); - if (this._last_acks.length >= 10) { - this._last_acks.shift(); + if (this._pendingAck.size) { + const ack = new RequestState(new Api.MsgsAck({ msgIds: Array(...this._pendingAck) })); + this._sendQueue.append(ack); + this._lastAcks.push(ack); + if (this._lastAcks.length >= 10) { + this._lastAcks.shift(); } - this._pending_ack.clear(); + this._pendingAck.clear(); } }; @@ -514,11 +599,11 @@ class MTProtoSender { // TODO Wait for the connection send queue to be empty? // This means that while it's not empty we can wait for // more messages to be added to the send queue. - await this._send_queue.wait(); + await this._sendQueue.wait(); if (this._isFallback) { // We don't long-poll on main loop, instead we have a separate loop for that - this.send(new HttpWait({ + this.send(new Api.HttpWait({ maxDelay: 0, waitAfter: 0, maxWait: 0, @@ -528,7 +613,7 @@ class MTProtoSender { // If we've had new ACKs appended while waiting for messages to send, add them to queue appendAcks(); - const res = await this._send_queue.get(); + const res = await this._sendQueue.get(); this.logWithIndex.debug(`Got ${res?.batch.length} message(s) to send`); @@ -542,12 +627,12 @@ class MTProtoSender { for (const state of batch) { if (!Array.isArray(state)) { if (state.request.classType === 'request' && state.request.className !== 'HttpWait') { - this._pending_state.set(state.msgId, state); + this._pendingState.set(state.msgId!, state); } } else { for (const s of state) { if (s.request.classType === 'request' && s.request.className !== 'HttpWait') { - this._pending_state.set(s.msgId, s); + this._pendingState.set(s.msgId, s); } } } @@ -555,7 +640,7 @@ class MTProtoSender { if (this.isReconnecting) { this.logWithIndex.debug('Reconnecting :('); - this._send_loop_handle = undefined; + this._sendLoopHandle = undefined; return; } @@ -565,12 +650,12 @@ class MTProtoSender { data = await this._state.encryptMessageData(data); try { - await this.getConnection().send(data); - } catch (e) { + await this.getConnection()!.send(data); + } catch (e: any) { this.logWithIndex.debug(`Connection closed while sending data ${e}`); this._log.error(e); this._log.info('Connection closed while sending data'); - this._send_loop_handle = undefined; + this._sendLoopHandle = undefined; if (!this.userDisconnected) { this.reconnect(); } @@ -579,12 +664,12 @@ class MTProtoSender { for (const state of batch) { if (!Array.isArray(state)) { if (state.request.className === 'HttpWait') { - state.resolve(); + state.resolve?.(); } } else { for (const s of state) { if (s.request.className === 'HttpWait') { - state.resolve(); + state.resolve?.(); } } } @@ -595,19 +680,19 @@ class MTProtoSender { } } - this._send_loop_handle = undefined; + this._sendLoopHandle = undefined; } async _recvLoop() { let body; let message; - while (this._user_connected && !this.isReconnecting) { + while (this._userConnected && !this.isReconnecting) { this._log.debug('Receiving items from the network...'); this.logWithIndex.debug('Receiving items from the network...'); try { - body = await this.getConnection().recv(); - } catch (e) { + body = await this.getConnection()!.recv(); + } catch (e: any) { // this._log.info('Connection closed while receiving data'); /** when the server disconnects us we want to reconnect */ if (!this.userDisconnected) { @@ -615,13 +700,14 @@ class MTProtoSender { this._log.warn('Connection closed while receiving data'); this.reconnect(); } - this._recv_loop_handle = undefined; + this._recvLoopHandle = undefined; return; } try { - message = await this._state.decryptMessageData(body); - } catch (e) { + // TODO: Handle `DecryptedDataBlock` in calls like a regular `TLMessage` rather than `Buffer` + message = (await this._state.decryptMessageData(body)) as TLMessage; + } catch (e: any) { this.logWithIndex.debug(`Error while receiving items from the network ${e.toString()}`); if (e instanceof TypeNotFoundError) { // Received object which we don't know how to deserialize @@ -643,22 +729,22 @@ class MTProtoSender { this._log.warn(`Invalid buffer ${e.code} for dc ${this._dcId}`); this.reconnect(); } - this._recv_loop_handle = undefined; + this._recvLoopHandle = undefined; return; } else { this._log.error('Unhandled error while receiving data'); this._log.error(e); this.reconnect(); - this._recv_loop_handle = undefined; + this._recvLoopHandle = undefined; return; } } try { await this._processMessage(message); - } catch (e) { + } catch (e: any) { // `RPCError` errors except for 'AUTH_KEY_UNREGISTERED' should be handled by the client if (e instanceof RPCError) { - if (e.message === 'AUTH_KEY_UNREGISTERED' || e.message === 'SESSION_REVOKED') { + if (e.errorMessage === 'AUTH_KEY_UNREGISTERED' || e.errorMessage === 'SESSION_REVOKED') { // 'AUTH_KEY_UNREGISTERED' for the main sender is thrown when unauthorized and should be ignored this._handleBadAuthKey(true); } @@ -671,21 +757,21 @@ class MTProtoSender { void this.checkLongPoll(); } - this._recv_loop_handle = undefined; + this._recvLoopHandle = undefined; } checkLongPoll() { if (this.isSendingLongPoll || !this._isFallback) return; this.isSendingLongPoll = true; - this.send(new HttpWait({ + this.send(new Api.HttpWait({ maxDelay: LONGPOLL_MAX_DELAY, waitAfter: LONGPOLL_WAIT_AFTER, maxWait: LONGPOLL_MAX_WAIT, }), undefined, true); } - _handleBadAuthKey(shouldSkipForMain) { + _handleBadAuthKey(shouldSkipForMain?: boolean) { if (shouldSkipForMain && this._isMainSender) { return; } @@ -709,14 +795,14 @@ class MTProtoSender { * @returns {Promise} * @private */ - async _processMessage(message) { + async _processMessage(message: TLMessage) { if (message.obj.className === 'MsgsAck') return; this.logWithIndex.debug(`Process message ${message.obj.className}`); - this._pending_ack.add(message.msgId); + this._pendingAck.add(message.msgId); - if (this.getConnection().shouldLongPoll) { - this._send_queue.setReady(true); + if (this.getConnection()!.shouldLongPoll) { + this._sendQueue.setReady?.(true); } // eslint-disable-next-line require-atomic-updates message.obj = await message.obj; @@ -735,29 +821,29 @@ class MTProtoSender { * @returns {*[]} * @private */ - _popStates(msgId) { - const state = this._pending_state.getAndDelete(msgId); + _popStates(msgId: BigInt.BigInteger) { + const state = this._pendingState.getAndDelete(msgId); if (state) { return [state]; } - const toPop = []; + const toPop: BigInt.BigInteger[] = []; - for (const pendingState of this._pending_state.values()) { + for (const pendingState of this._pendingState.values()) { if (pendingState.containerId?.equals(msgId)) { - toPop.push(pendingState.msgId); + toPop.push(pendingState.msgId!); } } if (toPop.length) { const temp = []; for (const x of toPop) { - temp.push(this._pending_state.getAndDelete(x)); + temp.push(this._pendingState.getAndDelete(x)); } return temp; } - for (const ack of this._last_acks) { + for (const ack of this._lastAcks) { if (ack.msgId === msgId) { return [ack]; } @@ -774,9 +860,9 @@ class MTProtoSender { * @returns {Promise} * @private */ - _handleRPCResult(message) { + _handleRPCResult(message: TLMessage) { const result = message.obj; - const state = this._pending_state.getAndDelete(result.reqMsgId); + const state = this._pendingState.getAndDelete(result.reqMsgId); this._log.debug(`Handling RPC result for message ${result.reqMsgId}`); if (!state) { @@ -786,8 +872,8 @@ class MTProtoSender { // which contain the real response right after. try { const reader = new BinaryReader(result.body); - if (!(reader.tgReadObject() instanceof upload.File)) { - throw new TypeNotFoundError('Not an upload.File'); + if (!(reader.tgReadObject() instanceof Api.upload.File)) { + throw new TypeNotFoundError(0, Buffer.alloc(0)); } } catch (e) { if (e instanceof TypeNotFoundError) { @@ -807,17 +893,17 @@ class MTProtoSender { if (result.error) { // eslint-disable-next-line new-cap const error = RPCMessageToError(result.error, state.request); - this._send_queue.append(new RequestState(new MsgsAck({ msgIds: [state.msgId] }))); - state.reject(error); + this._sendQueue.append(new RequestState(new Api.MsgsAck({ msgIds: [state.msgId!] }))); + state.reject?.(error); throw error; } else { try { const reader = new BinaryReader(result.body); const read = state.request.readResult(reader); this.logWithIndex.debug('Handling RPC result', read); - state.resolve(read); - } catch (err) { - state.reject(err); + state.resolve?.(read); + } catch (err: any) { + state.reject?.(err); throw err; } } @@ -830,7 +916,7 @@ class MTProtoSender { * @returns {Promise} * @private */ - async _handleContainer(message) { + async _handleContainer(message: TLMessage) { this._log.debug('Handling container'); for (const innerMessage of message.obj.messages) { await this._processMessage(innerMessage); @@ -844,14 +930,14 @@ class MTProtoSender { * @returns {Promise} * @private */ - async _handleGzipPacked(message) { + async _handleGzipPacked(message: TLMessage) { this._log.debug('Handling gzipped data'); const reader = new BinaryReader(message.obj.data); message.obj = reader.tgReadObject(); await this._processMessage(message); } - _handleUpdate(message) { + _handleUpdate(message: TLMessage) { if (message.obj.SUBCLASS_OF_ID !== 0x8af52aac) { // crc32(b'Updates') this._log.warn(`Note: ${message.obj.className} is not an update, not dispatching it`); @@ -871,7 +957,7 @@ class MTProtoSender { * @returns {Promise} * @private */ - _handlePong(message) { + _handlePong(message: TLMessage) { const pong = message.obj; const newTimeOffset = this._state.updateTimeOffset(message.msgId); @@ -880,11 +966,11 @@ class MTProtoSender { } this._log.debug(`Handling pong for message ${pong.msgId}`); - const state = this._pending_state.getAndDelete(pong.msgId); + const state = this._pendingState.getAndDelete(pong.msgId); // Todo Check result if (state) { - state.resolve(pong); + state.resolve?.(pong); } } @@ -897,12 +983,12 @@ class MTProtoSender { * @returns {Promise} * @private */ - _handleBadServerSalt(message) { + _handleBadServerSalt(message: TLMessage) { const badSalt = message.obj; this._log.debug(`Handling bad salt for message ${badSalt.badMsgId}`); this._state.salt = badSalt.newServerSalt; const states = this._popStates(badSalt.badMsgId); - this._send_queue.extend(states); + this._sendQueue.extend(states); this._log.debug(`${states.length} message(s) will be resent`); } @@ -915,7 +1001,7 @@ class MTProtoSender { * @returns {Promise} * @private */ - _handleBadNotification(message) { + _handleBadNotification(message: TLMessage) { const badMsg = message.obj; const states = this._popStates(badMsg.badMsgId); this._log.debug(`Handling bad msg ${JSON.stringify(badMsg)}`); @@ -944,7 +1030,7 @@ class MTProtoSender { return; } // Messages are to be re-sent once we've corrected the issue - this._send_queue.extend(states); + this._sendQueue.extend(states); this._log.debug(`${states.length} messages will be resent due to bad msg`); } @@ -956,11 +1042,11 @@ class MTProtoSender { * @returns {Promise} * @private */ - _handleDetailedInfo(message) { + _handleDetailedInfo(message: TLMessage) { // TODO https://goo.gl/VvpCC6 const msgId = message.obj.answerMsgId; this._log.debug(`Handling detailed info for message ${msgId}`); - this._pending_ack.add(msgId); + this._pendingAck.add(msgId); } /** @@ -971,11 +1057,11 @@ class MTProtoSender { * @returns {Promise} * @private */ - _handleNewDetailedInfo(message) { + _handleNewDetailedInfo(message: TLMessage) { // TODO https://goo.gl/VvpCC6 const msgId = message.obj.answerMsgId; this._log.debug(`Handling new detailed info for message ${msgId}`); - this._pending_ack.add(msgId); + this._pendingAck.add(msgId); } /** @@ -986,7 +1072,7 @@ class MTProtoSender { * @returns {Promise} * @private */ - _handleNewSessionCreated(message) { + _handleNewSessionCreated(message: TLMessage) { // TODO https://goo.gl/LMyN7A this._log.debug('Handling new session created'); this._state.salt = message.obj.serverSalt; @@ -1006,14 +1092,14 @@ class MTProtoSender { * @returns {Promise} * @private */ - _handleFutureSalts(message) { + _handleFutureSalts(message: TLMessage) { // TODO save these salts and automatically adjust to the // correct one whenever the salt in use expires. this._log.debug(`Handling future salts for message ${message.msgId}`); - const state = this._pending_state.getAndDelete(message.msgId); + const state = this._pendingState.getAndDelete(message.msgId); if (state) { - state.resolve(message.obj); + state.resolve?.(message.obj); } } @@ -1024,12 +1110,14 @@ class MTProtoSender { * @returns {Promise} * @private */ - _handleStateForgotten(message) { - this._send_queue.append( - new RequestState(new MsgsStateInfo({ - msgId: message.msgId, - query: String.fromCharCode(1).repeat(message.obj.msgIds), - })), + _handleStateForgotten(message: TLMessage) { + this._sendQueue.append( + new RequestState( + new Api.MsgsStateInfo({ + reqMsgId: message.msgId, + info: String.fromCharCode(1).repeat(message.obj.msgIds), + }), + ), ); } @@ -1042,17 +1130,17 @@ class MTProtoSender { * @private */ // eslint-disable-next-line @typescript-eslint/no-unused-vars - _handleMsgAll(message) { + _handleMsgAll(message: TLMessage) { } reconnect() { - if (this._user_connected && !this.isReconnecting) { + if (this._userConnected && !this.isReconnecting) { this.isReconnecting = true; // TODO Should we set this? // this._user_connected = false // we want to wait a second between each reconnect try to not flood the server with reconnects // in case of internal server issues. - Helpers.sleep(1000) + sleep(1000) .then(() => { this.logWithIndex.log('Reconnecting...'); this._log.info('Started reconnecting'); @@ -1062,42 +1150,47 @@ class MTProtoSender { } async _reconnect() { + const currentConnection = this._connection!; + const currentFallbackConnection = this._fallbackConnection; this._log.debug('Closing current connection...'); try { this.logWithIndex.warn('[Reconnect] Closing current connection...'); - await this._disconnect(this.getConnection()); - } catch (err) { + if (currentConnection) await this._disconnect(currentConnection); + if (currentFallbackConnection) await this._disconnect(currentFallbackConnection); + } catch (err: any) { this._log.warn(err); } - this._send_queue.append(undefined); + this._sendQueue.append(undefined); this._state.reset(); // For some reason reusing existing connection caused stuck requests - const newConnection = new this._connection.constructor( - this._connection._ip, - this._connection._port, - this._connection._dcId, - this._connection._log, - this._connection._testServers, - ); - const newFallbackConnection = new this._fallbackConnection.constructor( - this._connection._ip, - this._connection._port, - this._connection._dcId, - this._connection._log, - this._connection._testServers, - ); + // @ts-ignore + const newConnection = new currentConnection.constructor({ + ip: currentConnection._ip, + port: currentConnection._port, + dcId: currentConnection._dcId, + loggers: currentConnection._log, + isTestServer: currentConnection._isTestServer, + isPremium: currentConnection._isPremium, + }); + // @ts-ignore + const newFallbackConnection = new this._fallbackConnection.constructor({ + ip: currentConnection._ip, + port: currentConnection._port, + dcId: currentConnection._dcId, + loggers: currentConnection._log, + isTestServer: currentConnection._isTestServer, + isPremium: currentConnection._isPremium, + }); await this.connect(newConnection, true, newFallbackConnection); this.isReconnecting = false; - this._send_queue.prepend(this._pending_state.values()); - this._pending_state.clear(); + this._sendQueue.prepend(this._pendingState.values()); + this._pendingState.clear(); if (this._autoReconnectCallback) { await this._autoReconnectCallback(); } } } - -module.exports = MTProtoSender; diff --git a/src/lib/gramjs/network/MTProtoState.js b/src/lib/gramjs/network/MTProtoState.ts similarity index 76% rename from src/lib/gramjs/network/MTProtoState.js rename to src/lib/gramjs/network/MTProtoState.ts index f8c6b1100..5cfaf2886 100644 --- a/src/lib/gramjs/network/MTProtoState.js +++ b/src/lib/gramjs/network/MTProtoState.ts @@ -1,21 +1,47 @@ -const BigInt = require('big-integer'); -const aes = require('@cryptography/aes'); +import BigInt from 'big-integer'; -const Helpers = require('../Helpers'); -const IGE = require('../crypto/IGE'); -const BinaryReader = require('../extensions/BinaryReader'); -const GZIPPacked = require('../tl/core/GZIPPacked'); -const { TLMessage } = require('../tl/core'); -const { - SecurityError, - InvalidBufferError, -} = require('../errors/Common'); -const { InvokeAfterMsg } = require('../tl').requests; -const { +import type { AuthKey } from '../crypto/AuthKey'; + +import { IGE } from '../crypto/IGE'; +import { BinaryReader, type BinaryWriter, type Logger } from '../extensions'; +import { Api } from '../tl'; +import { TLMessage } from '../tl/core'; +import GZIPPacked from '../tl/core/GZIPPacked'; + +import { InvalidBufferError, SecurityError } from '../errors/Common'; +import { + convertToLittle, + generateRandomBytes, + generateRandomLong, + mod, + readBigIntFromBuffer, + readBufferFromBigInt, + sha256, toSignedLittleBuffer, -} = require('../Helpers'); +} from '../Helpers'; +import { CTR } from '../crypto/CTR'; + +export default class MTProtoState { + private readonly authKey?: AuthKey; + + private _log: any; + + timeOffset: number; + + salt: bigInt.BigInteger; + + private id: bigInt.BigInteger; + + _sequence: number; + + _isCall: boolean; + + _isOutgoing: boolean; + + private _lastMsgId: bigInt.BigInteger; + + private msgIds: string[]; -class MTProtoState { /** * `telethon.network.mtprotosender.MTProtoSender` needs to hold a state @@ -43,17 +69,17 @@ class MTProtoState { * @param isCall * @param isOutgoing */ - constructor(authKey, loggers, isCall = false, isOutgoing = false) { + constructor(authKey?: AuthKey, loggers?: Logger, isCall = false, isOutgoing = false) { this.authKey = authKey; this._log = loggers; this._isCall = isCall; this._isOutgoing = isOutgoing; this.timeOffset = 0; - this.salt = 0; + this.salt = BigInt.zero; - this.id = undefined; - this._sequence = undefined; - this._lastMsgId = undefined; + this.id = BigInt.zero; + this._sequence = 0; + this._lastMsgId = BigInt.zero; this.msgIds = []; this.reset(); } @@ -63,7 +89,7 @@ class MTProtoState { */ reset() { // Session IDs can be random on every connection - this.id = Helpers.generateRandomLong(true); + this.id = generateRandomLong(true); this._sequence = 0; this._lastMsgId = BigInt(0); this.msgIds = []; @@ -74,7 +100,7 @@ class MTProtoState { * used when the time offset changed. * @param message */ - updateMessageId(message) { + updateMessageId(message: TLMessage) { message.msgId = this._getNewMsgId(); } @@ -85,11 +111,13 @@ class MTProtoState { * @param client * @returns {{iv: Buffer, key: Buffer}} */ - async _calcKey(authKey, msgKey, client) { - const x = (this._isCall ? 128 + ((this._isOutgoing ^ client) ? 8 : 0) : (client === true ? 0 : 8)); + async _calcKey(authKey: Buffer, msgKey: Buffer, client: boolean) { + const x = this._isCall + ? (128 + (this._isOutgoing !== client ? 8 : 0)) + : (client ? 0 : 8); const [sha256a, sha256b] = await Promise.all([ - Helpers.sha256(Buffer.concat([msgKey, authKey.slice(x, x + 36)])), - Helpers.sha256(Buffer.concat([authKey.slice(x + 40, x + 76), msgKey])), + sha256(Buffer.concat([msgKey, authKey.slice(x, x + 36)])), + sha256(Buffer.concat([authKey.slice(x + 40, x + 76), msgKey])), ]); const key = Buffer.concat([sha256a.slice(0, 8), sha256b.slice(8, 24), sha256a.slice(24, 32)]); if (this._isCall) { @@ -115,7 +143,7 @@ class MTProtoState { * @param contentRelated * @param afterId */ - async writeDataAsMessage(buffer, data, contentRelated, afterId) { + async writeDataAsMessage(buffer: BinaryWriter, data: Buffer, contentRelated: boolean, afterId?: BigInt.BigInteger) { const msgId = this._getNewMsgId(); const seqNo = this._getSeqNo(contentRelated); let body; @@ -123,7 +151,7 @@ class MTProtoState { body = await GZIPPacked.gzipIfSmaller(contentRelated, data); } else { // Invoke query expects a query with a getBytes func - body = await GZIPPacked.gzipIfSmaller(contentRelated, new InvokeAfterMsg({ + body = await GZIPPacked.gzipIfSmaller(contentRelated, new Api.InvokeAfterMsg({ msgId: afterId, query: { getBytes() { @@ -147,8 +175,21 @@ class MTProtoState { * following MTProto 2.0 guidelines core.telegram.org/mtproto/description. * @param data */ - async encryptMessageData(data) { + async encryptMessageData(data: Buffer) { + if (!this.authKey) { + throw new Error('Auth key unset'); + } + await this.authKey.waitForKey(); + const authKey = this.authKey.getKey(); + if (!authKey) { + throw new Error('Auth key unset'); + } + + if (!this.salt || !this.id || !authKey || !this.authKey.keyId) { + throw new Error('Unset params'); + } + if (this._isCall) { const x = 128 + (this._isOutgoing ? 0 : 8); const lengthStart = data.length; @@ -158,7 +199,7 @@ class MTProtoState { data = Buffer.concat([data, Buffer.from(new Array(4 - (lengthStart % 4)).fill(0x20))]); } - const msgKeyLarge = await Helpers.sha256(Buffer.concat([this.authKey.getKey() + const msgKeyLarge = await sha256(Buffer.concat([authKey .slice(88 + x, 88 + x + 32), Buffer.from(data)])); const msgKey = msgKeyLarge.slice(8, 24); @@ -166,19 +207,19 @@ class MTProtoState { const { iv, key, - } = await this._calcKey(this.authKey.getKey(), msgKey, true); + } = await this._calcKey(authKey, msgKey, true); - data = Helpers.convertToLittle(new aes.CTR(key, iv).encrypt(data)); + data = new CTR(key, iv).encrypt(data); // data = data.slice(0, lengthStart) return Buffer.concat([msgKey, data]); } else { const s = toSignedLittleBuffer(this.salt, 8); const i = toSignedLittleBuffer(this.id, 8); data = Buffer.concat([Buffer.concat([s, i]), data]); - const padding = Helpers.generateRandomBytes(Helpers.mod(-(data.length + 12), 16) + 12); + const padding = generateRandomBytes(mod(-(data.length + 12), 16) + 12); // Being substr(what, offset, length); x = 0 for client // "msg_key_large = SHA256(substr(auth_key, 88+x, 32) + pt + padding)" - const msgKeyLarge = await Helpers.sha256(Buffer.concat([this.authKey.getKey() + const msgKeyLarge = await sha256(Buffer.concat([authKey .slice(88, 88 + 32), data, padding])); // "msg_key = substr (msg_key_large, 8, 16)" const msgKey = msgKeyLarge.slice(8, 24); @@ -186,9 +227,9 @@ class MTProtoState { const { iv, key, - } = await this._calcKey(this.authKey.getKey(), msgKey, true); + } = await this._calcKey(authKey, msgKey, true); - const keyId = Helpers.readBufferFromBigInt(this.authKey.keyId, 8); + const keyId = readBufferFromBigInt(this.authKey.keyId, 8); return Buffer.concat([keyId, msgKey, new IGE(key, iv).encryptIge(Buffer.concat([data, padding]))]); } } @@ -197,7 +238,11 @@ class MTProtoState { * Inverse of `encrypt_message_data` for incoming server messages. * @param body */ - async decryptMessageData(body) { + async decryptMessageData(body: Buffer) { + if (!this.authKey) { + throw new Error('Auth key unset'); + } + if (body.length < 8) { throw new InvalidBufferError(body); } @@ -209,19 +254,23 @@ class MTProtoState { } // TODO Check salt,sessionId, and sequenceNumber if (!this._isCall) { - const keyId = Helpers.readBigIntFromBuffer(body.slice(0, 8)); + const keyId = readBigIntFromBuffer(body.slice(0, 8)); - if (keyId.neq(this.authKey.keyId)) { + if (!this.authKey.keyId || keyId.neq(this.authKey.keyId)) { throw new SecurityError('Server replied with an invalid auth key'); } } + const authKey = this.authKey.getKey(); + if (!authKey) { + throw new SecurityError('Unset AuthKey'); + } const msgKey = this._isCall ? body.slice(0, 16) : body.slice(8, 24); - const x = this._isCall ? 128 + (this.isOutgoing ? 8 : 0) : undefined; + const x = this._isCall ? 128 + (this._isOutgoing ? 8 : 0) : 0; const { iv, key, - } = await this._calcKey(this.authKey.getKey(), msgKey, false); + } = await this._calcKey(authKey, msgKey, false); if (this._isCall) { body = body.slice(16); @@ -229,7 +278,7 @@ class MTProtoState { body = Buffer.concat([body, Buffer.from(new Array(4 - (lengthStart % 4)).fill(0))]); - body = Helpers.convertToLittle(new aes.CTR(key, iv).decrypt(body)); + body = new CTR(key, iv).decrypt(body); body = body.slice(0, lengthStart); } else { @@ -239,9 +288,9 @@ class MTProtoState { // Sections "checking sha256 hash" and "message length" const ourKey = this._isCall - ? await Helpers.sha256(Buffer.concat([this.authKey.getKey() + ? await sha256(Buffer.concat([authKey .slice(88 + x, 88 + x + 32), body])) - : await Helpers.sha256(Buffer.concat([this.authKey.getKey() + : await sha256(Buffer.concat([authKey .slice(96, 96 + 32), body])); if (!this._isCall && !msgKey.equals(ourKey.slice(8, 24))) { @@ -323,7 +372,7 @@ class MTProtoState { /** * Returns the understood time by the message id (server time + local offset) */ - getMsgIdTimeLocal(msgId) { + getMsgIdTimeLocal(msgId: BigInt.BigInteger) { if (this._lastMsgId.eq(0)) { // this means it's the first message sent/received so don't check yet return false; @@ -336,11 +385,11 @@ class MTProtoState { * one given a known valid message ID. * @param correctMsgId {BigInteger} */ - updateTimeOffset(correctMsgId) { + updateTimeOffset(correctMsgId: BigInt.BigInteger) { const bad = this._getNewMsgId(); const old = this.timeOffset; const now = Math.floor(Date.now() / 1000); - const correct = correctMsgId.shiftRight(BigInt(32)); + const correct = correctMsgId.shiftRight(BigInt(32)).toJSNumber(); this.timeOffset = correct - now; if (this.timeOffset !== old) { @@ -359,7 +408,7 @@ class MTProtoState { * @param contentRelated * @private */ - _getSeqNo(contentRelated) { + _getSeqNo(contentRelated: boolean) { if (contentRelated) { const result = this._sequence * 2 + 1; this._sequence += 1; @@ -369,5 +418,3 @@ class MTProtoState { } } } - -module.exports = MTProtoState; diff --git a/src/lib/gramjs/network/RequestState.js b/src/lib/gramjs/network/RequestState.js deleted file mode 100644 index c07500c93..000000000 --- a/src/lib/gramjs/network/RequestState.js +++ /dev/null @@ -1,36 +0,0 @@ -const Deferred = require('../../../util/Deferred').default; - -class RequestState { - constructor(request, abortSignal = undefined) { - this.containerId = undefined; - this.msgId = undefined; - this.request = request; - this.data = request.getBytes(); - this.after = undefined; - this.result = undefined; - this.abortSignal = abortSignal; - this.finished = new Deferred(); - - this.resetPromise(); - } - - isReady() { - if (!this.after) { - return true; - } - - return this.after.finished.promise; - } - - resetPromise() { - // Prevent stuck await - this.reject?.(); - - this.promise = new Promise((resolve, reject) => { - this.resolve = resolve; - this.reject = reject; - }); - } -} - -module.exports = RequestState; diff --git a/src/lib/gramjs/network/RequestState.ts b/src/lib/gramjs/network/RequestState.ts new file mode 100644 index 000000000..86a2929b0 --- /dev/null +++ b/src/lib/gramjs/network/RequestState.ts @@ -0,0 +1,63 @@ +import type BigInt from 'big-integer'; + +import type { Api } from '../tl'; + +import Deferred from '../../../util/Deferred'; + +export type CallableRequest = Api.AnyRequest | Api.MsgsAck | Api.MsgsStateInfo | Api.HttpWait; +type RequestResponse = T extends { __response: infer R } ? R : void; + +export default class RequestState { + public containerId?: BigInt.BigInteger; + + public msgId?: BigInt.BigInteger; + + public request: any; + + public data: Buffer; + + public after: any; + + public result: undefined; + + public finished: Deferred; + + public promise: Promise | undefined> | undefined; + + public abortSignal: AbortSignal | undefined; + + public resolve?: (value?: RequestResponse) => void; + + public reject?: (reason?: Error) => void; + + constructor(request: T, abortSignal?: AbortSignal) { + this.containerId = undefined; + this.msgId = undefined; + this.request = request; + this.data = request.getBytes(); + this.after = undefined; + this.result = undefined; + this.abortSignal = abortSignal; + this.finished = new Deferred(); + + this.resetPromise(); + } + + isReady() { + if (!this.after) { + return true; + } + + return this.after.finished.promise; + } + + resetPromise() { + // Prevent stuck await + this.reject?.(); + + this.promise = new Promise | undefined>((resolve, reject) => { + this.resolve = resolve; + this.reject = reject; + }); + } +} diff --git a/src/lib/gramjs/network/connection/Connection.js b/src/lib/gramjs/network/connection/Connection.ts similarity index 69% rename from src/lib/gramjs/network/connection/Connection.js rename to src/lib/gramjs/network/connection/Connection.ts index 8f47859d8..91e04355c 100644 --- a/src/lib/gramjs/network/connection/Connection.js +++ b/src/lib/gramjs/network/connection/Connection.ts @@ -1,6 +1,18 @@ -const PromisedWebSockets = require('../../extensions/PromisedWebSockets'); -const HttpStream = require('../../extensions/HttpStream').default; -const AsyncQueue = require('../../extensions/AsyncQueue'); +import type { Logger } from '../../extensions'; +import type { AbridgedPacketCodec } from './TCPAbridged'; + +import { AsyncQueue, PromisedWebSockets } from '../../extensions'; + +import HttpStream from '../../extensions/HttpStream'; + +interface ConnectionInterfaceParams { + ip: string; + port: number; + dcId: number; + loggers: Logger; + isPremium?: boolean; + isTestServer?: boolean; +} /** * The `Connection` class is a wrapper around ``asyncio.open_connection``. @@ -13,15 +25,47 @@ const AsyncQueue = require('../../extensions/AsyncQueue'); * ``ConnectionError``, which will raise when attempting to send if * the client is disconnected (includes remote disconnections). */ -class Connection { - PacketCodecClass = undefined; +export class Connection { + PacketCodecClass?: typeof AbridgedPacketCodec; - constructor(ip, port, dcId, loggers, testServers, isPremium) { + readonly _ip: string; + + readonly _port: number; + + _dcId: number; + + _log: Logger; + + _connected: boolean; + + _isPremium?: boolean; + + shouldLongPoll: boolean; + + private _sendTask?: Promise; + + private _recvTask?: Promise; + + protected _codec: any; + + protected _obfuscation: any; + + _sendArray: AsyncQueue; + + _recvArray: AsyncQueue; + + socket: PromisedWebSockets | HttpStream; + + public _isTestServer?: boolean; + + constructor({ + ip, port, dcId, loggers, isPremium, isTestServer, + }: ConnectionInterfaceParams) { this._ip = ip; this._port = port; this._dcId = dcId; this._log = loggers; - this._testServers = testServers; + this._isTestServer = isTestServer; this._isPremium = isPremium; this._connected = false; @@ -29,8 +73,8 @@ class Connection { this._recvTask = undefined; this._codec = undefined; this._obfuscation = undefined; // TcpObfuscated and MTProxy - this._sendArray = new AsyncQueue(); - this._recvArray = new AsyncQueue(); + this._sendArray = new AsyncQueue(); + this._recvArray = new AsyncQueue(); // this.socket = new PromiseSocket(new Socket()) this.shouldLongPoll = false; @@ -47,10 +91,10 @@ class Connection { async _connect() { this._log.debug('Connecting'); - this._codec = new this.PacketCodecClass(this); - await this.socket.connect(this._port, this._ip, this._testServers, this._isPremium); + this._codec = new this.PacketCodecClass!(this); + await this.socket.connect(this._port, this._ip, this._isTestServer, this._isPremium); this._log.debug('Finished connecting'); - // await this.socket.connect({host: this._ip, port: this._port}); + await this._initConn(); } @@ -76,7 +120,7 @@ class Connection { } } - async send(data) { + async send(data: Buffer) { if (!this._connected) { throw new Error('Not connected'); } @@ -135,7 +179,7 @@ class Connection { } } - _send(data) { + _send(data: Buffer) { const encodedPacket = this._codec.encodePacket(data); this.socket.write(encodedPacket); } @@ -149,15 +193,15 @@ class Connection { } } -class ObfuscatedConnection extends Connection { - ObfuscatedIO = undefined; +export class ObfuscatedConnection extends Connection { + ObfuscatedIO: any = undefined; - _initConn() { + async _initConn() { this._obfuscation = new this.ObfuscatedIO(this); this.socket.write(this._obfuscation.header); } - _send(data) { + _send(data: Buffer) { this._obfuscation.write(this._codec.encodePacket(data)); } @@ -166,34 +210,40 @@ class ObfuscatedConnection extends Connection { } } -class PacketCodec { - constructor(connection) { +export class PacketCodec { + private _conn: Buffer; + + constructor(connection: Buffer) { this._conn = connection; } // eslint-disable-next-line @typescript-eslint/no-unused-vars - encodePacket(data) { + encodePacket(data: Buffer) { throw new Error('Not Implemented'); // Override } // eslint-disable-next-line @typescript-eslint/no-unused-vars - readPacket(reader) { + readPacket(reader: PromisedWebSockets) { // override throw new Error('Not Implemented'); } } -class HttpConnection extends Connection { - constructor(ip, port, dcId, loggers, testServers, isPremium) { - super(ip, port, dcId, loggers, testServers, isPremium); +export class HttpConnection extends Connection { + socket: HttpStream; + + href: string; + + constructor(params: ConnectionInterfaceParams) { + super(params); this.shouldLongPoll = true; this.socket = new HttpStream(this.disconnectCallback.bind(this)); - this.href = HttpStream.getURL(this._ip, this._port, this._testServers, this._isPremium); + this.href = HttpStream.getURL(this._ip, this._port, this._isTestServer, this._isPremium); } - send(data) { + send(data: Buffer) { return this.socket.write(data); } @@ -203,7 +253,7 @@ class HttpConnection extends Connection { async _connect() { this._log.debug('Connecting'); - await this.socket.connect(this._port, this._ip, this._testServers, this._isPremium); + await this.socket.connect(this._port, this._ip, this._isTestServer, this._isPremium); this._log.debug('Finished connecting'); } @@ -212,10 +262,3 @@ class HttpConnection extends Connection { this._connected = true; } } - -module.exports = { - Connection, - PacketCodec, - ObfuscatedConnection, - HttpConnection, -}; diff --git a/src/lib/gramjs/network/connection/TCPAbridged.js b/src/lib/gramjs/network/connection/TCPAbridged.ts similarity index 55% rename from src/lib/gramjs/network/connection/TCPAbridged.js rename to src/lib/gramjs/network/connection/TCPAbridged.ts index 5876d3f98..86241ea3c 100644 --- a/src/lib/gramjs/network/connection/TCPAbridged.js +++ b/src/lib/gramjs/network/connection/TCPAbridged.ts @@ -1,34 +1,39 @@ -const BigInt = require('big-integer'); -const { readBufferFromBigInt } = require('../../Helpers'); -const { - Connection, - PacketCodec, -} = require('./Connection'); +import BigInt from 'big-integer'; -class AbridgedPacketCodec extends PacketCodec { +import type { PromisedWebSockets } from '../../extensions'; + +import { readBufferFromBigInt } from '../../Helpers'; +import { Connection, PacketCodec } from './Connection'; + +export class AbridgedPacketCodec extends PacketCodec { static tag = Buffer.from('ef', 'hex'); static obfuscateTag = Buffer.from('efefefef', 'hex'); - constructor(props) { + private tag: Buffer; + + obfuscateTag: Buffer; + + constructor(props: any) { super(props); this.tag = AbridgedPacketCodec.tag; this.obfuscateTag = AbridgedPacketCodec.obfuscateTag; } - encodePacket(data) { - let length = data.length >> 2; + encodePacket(data: Buffer) { + const length = data.length >> 2; + let temp; if (length < 127) { const b = Buffer.alloc(1); b.writeUInt8(length, 0); - length = b; + temp = b; } else { - length = Buffer.concat([Buffer.from('7f', 'hex'), readBufferFromBigInt(BigInt(length), 3)]); + temp = Buffer.concat([Buffer.from('7f', 'hex'), readBufferFromBigInt(BigInt(length), 3)]); } - return Buffer.concat([length, data]); + return Buffer.concat([temp, data]); } - async readPacket(reader) { + async readPacket(reader: PromisedWebSockets) { const readData = await reader.read(1); let length = readData[0]; if (length >= 127) { @@ -45,11 +50,6 @@ class AbridgedPacketCodec extends PacketCodec { * only require 1 byte if the packet length is less than * 508 bytes (127 << 2, which is very common). */ -class ConnectionTCPAbridged extends Connection { +export class ConnectionTCPAbridged extends Connection { PacketCodecClass = AbridgedPacketCodec; } - -module.exports = { - ConnectionTCPAbridged, - AbridgedPacketCodec, -}; diff --git a/src/lib/gramjs/network/connection/TCPFull.js b/src/lib/gramjs/network/connection/TCPFull.js deleted file mode 100644 index 703cad555..000000000 --- a/src/lib/gramjs/network/connection/TCPFull.js +++ /dev/null @@ -1,57 +0,0 @@ -// CONTEST -// const { Connection, PacketCodec } = require('./Connection') -// const { crc32 } = require('../../Helpers') -// const { InvalidChecksumError } = require('../../errors/Common') -// -// class FullPacketCodec extends PacketCodec { -// constructor(connection) { -// super(connection) -// this._sendCounter = 0 // Telegram will ignore us otherwise -// } -// -// encodePacket(data) { -// // https://core.telegram.org/mtproto#tcp-transport -// // total length, sequence number, packet and checksum (CRC32) -// const length = data.length + 12 -// const e = Buffer.alloc(8) -// e.writeInt32LE(length,0) -// e.writeInt32LE(this._sendCounter,4) -// data = Buffer.concat([e, data]) -// const crc = Buffer.alloc(4) -// crc.writeUInt32LE(crc32(data),0) -// this._sendCounter += 1 -// return Buffer.concat([data, crc]) -// } -// -// /** -// * -// * @param reader {PromisedWebSockets} -// * @returns {Promise<*>} -// */ -// async readPacket(reader) { -// const packetLenSeq = await reader.read(8) // 4 and 4 -// // process.exit(0); -// if (packetLenSeq === undefined) { -// return false -// } -// const packetLen = packetLenSeq.readInt32LE(0) -// let body = await reader.read(packetLen - 8) -// const [checksum] = body.slice(-4).readUInt32LE(0) -// body = body.slice(0, -4) -// -// const validChecksum = crc32(Buffer.concat([packetLenSeq, body])) -// if (!(validChecksum === checksum)) { -// throw new InvalidChecksumError(checksum, validChecksum) -// } -// return body -// } -// } -// -// class ConnectionTCPFull extends Connection { -// PacketCodecClass = FullPacketCodec; -// } -// -// module.exports = { -// FullPacketCodec, -// ConnectionTCPFull, -// } diff --git a/src/lib/gramjs/network/connection/TCPObfuscated.js b/src/lib/gramjs/network/connection/TCPObfuscated.ts similarity index 71% rename from src/lib/gramjs/network/connection/TCPObfuscated.js rename to src/lib/gramjs/network/connection/TCPObfuscated.ts index dc3ccdf5a..458f1ee2b 100644 --- a/src/lib/gramjs/network/connection/TCPObfuscated.js +++ b/src/lib/gramjs/network/connection/TCPObfuscated.ts @@ -1,12 +1,21 @@ -const { generateRandomBytes } = require('../../Helpers'); -const { ObfuscatedConnection } = require('./Connection'); -const { AbridgedPacketCodec } = require('./TCPAbridged'); -const CTR = require('../../crypto/CTR'); +import type { HttpStream, PromisedWebSockets } from '../../extensions'; + +import { CTR } from '../../crypto/CTR'; + +import { generateRandomBytes } from '../../Helpers'; +import { ObfuscatedConnection } from './Connection'; +import { AbridgedPacketCodec } from './TCPAbridged'; class ObfuscatedIO { - header = undefined; + header?: Buffer = undefined; - constructor(connection) { + private connection: PromisedWebSockets | HttpStream; + + private _encrypt: CTR; + + private _decrypt: CTR; + + constructor(connection: ConnectionTCPObfuscated) { this.connection = connection.socket; const res = this.initHeader(connection.PacketCodecClass); this.header = res.random; @@ -15,10 +24,14 @@ class ObfuscatedIO { this._decrypt = res.decryptor; } - initHeader(packetCodec) { + initHeader(packetCodec: typeof AbridgedPacketCodec) { // Obfuscated messages secrets cannot start with any of these - const keywords = [Buffer.from('50567247', 'hex'), Buffer.from('474554', 'hex'), - Buffer.from('504f5354', 'hex'), Buffer.from('eeeeeeee', 'hex')]; + const keywords = [ + Buffer.from('50567247', 'hex'), + Buffer.from('474554', 'hex'), + Buffer.from('504f5354', 'hex'), + Buffer.from('eeeeeeee', 'hex'), + ]; let random; // eslint-disable-next-line no-constant-condition @@ -64,22 +77,18 @@ class ObfuscatedIO { }; } - async read(n) { + async read(n: number) { const data = await this.connection.readExactly(n); return this._decrypt.encrypt(data); } - write(data) { + write(data: Buffer) { this.connection.write(this._encrypt.encrypt(data)); } } -class ConnectionTCPObfuscated extends ObfuscatedConnection { +export class ConnectionTCPObfuscated extends ObfuscatedConnection { ObfuscatedIO = ObfuscatedIO; PacketCodecClass = AbridgedPacketCodec; } - -module.exports = { - ConnectionTCPObfuscated, -}; diff --git a/src/lib/gramjs/network/connection/index.js b/src/lib/gramjs/network/connection/index.js deleted file mode 100644 index e350e8873..000000000 --- a/src/lib/gramjs/network/connection/index.js +++ /dev/null @@ -1,12 +0,0 @@ -const { Connection, HttpConnection } = require('./Connection'); -const { ConnectionTCPFull } = require('./TCPFull'); -const { ConnectionTCPAbridged } = require('./TCPAbridged'); -const { ConnectionTCPObfuscated } = require('./TCPObfuscated'); - -module.exports = { - Connection, - HttpConnection, - ConnectionTCPFull, - ConnectionTCPAbridged, - ConnectionTCPObfuscated, -}; diff --git a/src/lib/gramjs/network/connection/index.ts b/src/lib/gramjs/network/connection/index.ts new file mode 100644 index 000000000..acb1711f4 --- /dev/null +++ b/src/lib/gramjs/network/connection/index.ts @@ -0,0 +1,3 @@ +export { Connection, HttpConnection } from './Connection'; +export { ConnectionTCPAbridged } from './TCPAbridged'; +export { ConnectionTCPObfuscated } from './TCPObfuscated'; diff --git a/src/lib/gramjs/network/index.js b/src/lib/gramjs/network/index.js deleted file mode 100644 index 6bdf19d92..000000000 --- a/src/lib/gramjs/network/index.js +++ /dev/null @@ -1,27 +0,0 @@ -const MTProtoPlainSender = require('./MTProtoPlainSender'); -const MTProtoSender = require('./MTProtoSender'); - -const { - Connection, - ConnectionTCPFull, - ConnectionTCPAbridged, - ConnectionTCPObfuscated, - HttpConnection, -} = require('./connection'); - -const { - UpdateConnectionState, - UpdateServerTimeOffset, -} = require('./updates'); - -module.exports = { - Connection, - HttpConnection, - ConnectionTCPFull, - ConnectionTCPAbridged, - ConnectionTCPObfuscated, - MTProtoPlainSender, - MTProtoSender, - UpdateConnectionState, - UpdateServerTimeOffset, -}; diff --git a/src/lib/gramjs/network/index.ts b/src/lib/gramjs/network/index.ts new file mode 100644 index 000000000..076cda725 --- /dev/null +++ b/src/lib/gramjs/network/index.ts @@ -0,0 +1,18 @@ +import { + Connection, ConnectionTCPAbridged, ConnectionTCPObfuscated, HttpConnection, +} from './connection'; +import { UpdateConnectionState, UpdateServerTimeOffset } from './updates'; + +import MTProtoPlainSender from './MTProtoPlainSender'; +import MTProtoSender from './MTProtoSender'; + +export { + Connection, + HttpConnection, + ConnectionTCPAbridged, + ConnectionTCPObfuscated, + MTProtoPlainSender, + MTProtoSender, + UpdateConnectionState, + UpdateServerTimeOffset, +}; diff --git a/src/lib/gramjs/network/updates.js b/src/lib/gramjs/network/updates.js deleted file mode 100644 index 0c42e7206..000000000 --- a/src/lib/gramjs/network/updates.js +++ /dev/null @@ -1,23 +0,0 @@ -class UpdateConnectionState { - static disconnected = -1; - - static connected = 1; - - static broken = 0; - - constructor(state, origin) { - this.state = state; - this.origin = origin; - } -} - -class UpdateServerTimeOffset { - constructor(timeOffset) { - this.timeOffset = timeOffset; - } -} - -module.exports = { - UpdateConnectionState, - UpdateServerTimeOffset, -}; diff --git a/src/lib/gramjs/network/updates.ts b/src/lib/gramjs/network/updates.ts new file mode 100644 index 000000000..70eb7558c --- /dev/null +++ b/src/lib/gramjs/network/updates.ts @@ -0,0 +1,21 @@ +export class UpdateConnectionState { + static disconnected = -1; + + static connected = 1; + + static broken = 0; + + state: number; + + constructor(state: number) { + this.state = state; + } +} + +export class UpdateServerTimeOffset { + timeOffset: number; + + constructor(timeOffset: number) { + this.timeOffset = timeOffset; + } +} diff --git a/src/lib/gramjs/sessions/Abstract.js b/src/lib/gramjs/sessions/Abstract.js deleted file mode 100644 index 1c30ebc13..000000000 --- a/src/lib/gramjs/sessions/Abstract.js +++ /dev/null @@ -1,174 +0,0 @@ -class Session { - /** - * Creates a clone of this session file - * @param toInstance {Session|null} - * @returns {Session} - */ - - /* CONTEST - clone(toInstance = null) { - return toInstance || new this.constructor() - } */ - - /** - * Returns the currently-used data center ID. - */ - get dcId() { - throw new Error('Not Implemented'); - } - - /** - * Returns the server address where the library should connect to. - */ - get serverAddress() { - throw new Error('Not Implemented'); - } - - /** - * Returns the port to which the library should connect to. - */ - get port() { - throw new Error('Not Implemented'); - } - - /** - * Returns an ``AuthKey`` instance associated with the saved - * data center, or `None` if a new one should be generated. - */ - get authKey() { - throw new Error('Not Implemented'); - } - - /** - * Sets the ``AuthKey`` to be used for the saved data center. - * @param value - */ - set authKey(value) { - throw new Error('Not Implemented'); - } - - /** - * Sets the information of the data center address and port that - * the library should connect to, as well as the data center ID, - * which is currently unused. - * @param dcId {number} - * @param serverAddress {string} - * @param port {number} - */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - setDC(dcId, serverAddress, port) { - throw new Error('Not implemented'); - } - - /** - * Returns an ID of the takeout process initialized for this session, - * or `None` if there's no were any unfinished takeout requests. - */ - /* CONTEST - get takeoutId() { - throw new Error('Not Implemented') - } - */ - /** - * Sets the ID of the unfinished takeout process for this session. - * @param value - */ - /* CONTEST - set takeoutId(value) { - throw new Error('Not Implemented') - } - */ - /** - * Returns the ``UpdateState`` associated with the given `entity_id`. - * If the `entity_id` is 0, it should return the ``UpdateState`` for - * no specific channel (the "general" state). If no state is known - * it should ``return None``. - * @param entityId - */ - /* CONTEST - getUpdateState(entityId) { - throw new Error('Not Implemented') - } - - */ - - /** - * Sets the given ``UpdateState`` for the specified `entity_id`, which - * should be 0 if the ``UpdateState`` is the "general" state (and not - * for any specific channel). - * @param entityId - * @param state - */ - /* CONTEST - setUpdateState(entityId, state) { - throw new Error('Not Implemented') - } - - */ - - /** - * Called on client disconnection. Should be used to - * free any used resources. Can be left empty if none. - */ - - /* CONTEST - close() { - - } - - */ - - /** - * called whenever important properties change. It should - * make persist the relevant session information to disk. - */ - save() { - throw new Error('Not Implemented'); - } - - /** - * Called upon client.log_out(). Should delete the stored - * information from disk since it's not valid anymore. - */ - - delete() { - throw new Error('Not Implemented'); - } - - /** - * Lists available sessions. Not used by the library itself. - */ - /* CONTEST - listSessions() { - throw new Error('Not Implemented') - } - - */ - - /** - * Processes the input ``TLObject`` or ``list`` and saves - * whatever information is relevant (e.g., ID or access hash). - * @param tlo - */ - /* CONTEST - processEntities(tlo) { - throw new Error('Not Implemented') - } - - */ - - /** - * Turns the given key into an ``InputPeer`` (e.g. ``InputPeerUser``). - * The library uses this method whenever an ``InputPeer`` is needed - * to suit several purposes (e.g. user only provided its ID or wishes - * to use a cached username to avoid extra RPC). - */ - /* CONTEST - getInputEntity(key) { - throw new Error('Not Implemented') - } - - */ -} - -module.exports = Session; diff --git a/src/lib/gramjs/sessions/Abstract.ts b/src/lib/gramjs/sessions/Abstract.ts new file mode 100644 index 000000000..11741ec56 --- /dev/null +++ b/src/lib/gramjs/sessions/Abstract.ts @@ -0,0 +1,23 @@ +import type { AuthKey } from '../crypto/AuthKey'; + +export default abstract class Session { + abstract setDC(dcId: number, serverAddress: string, port: number, isTestServer?: boolean): void; + + abstract get dcId(): number; + + abstract get serverAddress(): string; + + abstract get port(): number; + + abstract get isTestServer(): boolean | undefined; + + abstract getAuthKey(dcId?: number): AuthKey; + + abstract setAuthKey(authKey: AuthKey | undefined, dcId?: number): void; + + abstract save(): void; + + abstract load(): Promise; + + abstract delete(): void; +} diff --git a/src/lib/gramjs/sessions/CacheApiSession.js b/src/lib/gramjs/sessions/CacheApiSession.js deleted file mode 100644 index 5bd45aa4b..000000000 --- a/src/lib/gramjs/sessions/CacheApiSession.js +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-disable no-restricted-globals */ -const StorageSession = require('./StorageSession'); - -const CACHE_NAME = 'GramJs'; - -class CacheApiSession extends StorageSession { - async _delete() { - const request = new Request(this._storageKey); - const cache = await self.caches.open(CACHE_NAME); - return cache.delete(request); - } - - async _fetchFromCache() { - const request = new Request(this._storageKey); - const cache = await self.caches.open(CACHE_NAME); - const cached = await cache.match(request); - return cached ? cached.text() : undefined; - } - - async _saveToCache(data) { - const request = new Request(this._storageKey); - const response = new Response(data); - const cache = await self.caches.open(CACHE_NAME); - return cache.put(request, response); - } -} - -module.exports = CacheApiSession; diff --git a/src/lib/gramjs/sessions/CallbackSession.js b/src/lib/gramjs/sessions/CallbackSession.ts similarity index 61% rename from src/lib/gramjs/sessions/CallbackSession.js rename to src/lib/gramjs/sessions/CallbackSession.ts index d14e2fd86..04bf0ff0e 100644 --- a/src/lib/gramjs/sessions/CallbackSession.js +++ b/src/lib/gramjs/sessions/CallbackSession.ts @@ -1,9 +1,17 @@ -const MemorySession = require('./Memory'); -const AuthKey = require('../crypto/AuthKey'); -const utils = require('../Utils'); +import type { SessionData } from '../types'; -class CallbackSession extends MemorySession { - constructor(sessionData, callback) { +import { AuthKey } from '../crypto/AuthKey'; +import { getDC } from '../Utils'; +import MemorySession from './Memory'; + +export default class CallbackSession extends MemorySession { + private _sessionData?: SessionData; + + private _callback: (session?: SessionData) => void; + + private _authKeys: Record; + + constructor(sessionData: SessionData | undefined, callback: (session?: SessionData) => void) { super(); this._sessionData = sessionData; @@ -12,14 +20,6 @@ class CallbackSession extends MemorySession { this._authKeys = {}; } - get authKey() { - throw new Error('Not supported'); - } - - set authKey(value) { - throw new Error('Not supported'); - } - async load() { if (!this._sessionData) { return; @@ -34,30 +34,31 @@ class CallbackSession extends MemorySession { const { ipAddress, port, - } = utils.getDC(mainDcId); + } = getDC(mainDcId); this.setDC(mainDcId, ipAddress, port, isTest, true); await Promise.all(Object.keys(keys) - .map(async (dcId) => { + .map(async (dcIdStr) => { + const dcId = Number(dcIdStr); const key = typeof keys[dcId] === 'string' - ? Buffer.from(keys[dcId], 'hex') + ? Buffer.from(keys[dcId] as string, 'hex') : Buffer.from(keys[dcId]); if (hashes[dcId]) { const hash = typeof hashes[dcId] === 'string' - ? Buffer.from(hashes[dcId], 'hex') + ? Buffer.from(hashes[dcId] as string, 'hex') : Buffer.from(hashes[dcId]); this._authKeys[dcId] = new AuthKey(key, hash); } else { this._authKeys[dcId] = new AuthKey(); - await this._authKeys[dcId].setKey(key, true); + await this._authKeys[dcId].setKey(key); } })); } - setDC(dcId, serverAddress, port, isTestServer, skipOnUpdate = false) { + setDC(dcId: number, serverAddress: string, port: number, isTestServer?: boolean, skipOnUpdate = false) { this._dcId = dcId; this._serverAddress = serverAddress; this._port = port; @@ -74,14 +75,14 @@ class CallbackSession extends MemorySession { return this._authKeys[dcId]; } - setAuthKey(authKey, dcId = this._dcId) { + setAuthKey(authKey: AuthKey, dcId = this._dcId) { this._authKeys[dcId] = authKey; void this._onUpdate(); } getSessionData() { - const sessionData = { + const sessionData: SessionData = { mainDcId: this._dcId, keys: {}, hashes: {}, @@ -90,12 +91,13 @@ class CallbackSession extends MemorySession { Object .keys(this._authKeys) - .forEach((dcId) => { + .forEach((dcIdStr) => { + const dcId = Number(dcIdStr); const authKey = this._authKeys[dcId]; - if (!authKey || !authKey._key) return; + if (!authKey?._key) return; sessionData.keys[dcId] = authKey._key.toString('hex'); - sessionData.hashes[dcId] = authKey._hash.toString('hex'); + sessionData.hashes[dcId] = authKey._hash!.toString('hex'); }); return sessionData; @@ -109,5 +111,3 @@ class CallbackSession extends MemorySession { this._callback(undefined); } } - -module.exports = CallbackSession; diff --git a/src/lib/gramjs/sessions/IdbSession.js b/src/lib/gramjs/sessions/IdbSession.js deleted file mode 100644 index 42dfa39aa..000000000 --- a/src/lib/gramjs/sessions/IdbSession.js +++ /dev/null @@ -1,20 +0,0 @@ -const idb = require('idb-keyval'); -const StorageSession = require('./StorageSession'); - -const CACHE_NAME = 'GramJs'; - -class IdbSession extends StorageSession { - _delete() { - return idb.del(`${CACHE_NAME}:${this._storageKey}`); - } - - _fetchFromCache() { - return idb.get(`${CACHE_NAME}:${this._storageKey}`); - } - - _saveToCache(data) { - return idb.set(`${CACHE_NAME}:${this._storageKey}`, data); - } -} - -module.exports = IdbSession; diff --git a/src/lib/gramjs/sessions/LocalStorageSession.js b/src/lib/gramjs/sessions/LocalStorageSession.js deleted file mode 100644 index b64b982cc..000000000 --- a/src/lib/gramjs/sessions/LocalStorageSession.js +++ /dev/null @@ -1,17 +0,0 @@ -const StorageSession = require('./StorageSession'); - -class LocalStorageSession extends StorageSession { - _delete() { - return localStorage.removeItem(this._storageKey); - } - - _fetchFromCache() { - return localStorage.getItem(this._storageKey); - } - - _saveToCache(data) { - return localStorage.setItem(this._storageKey, data); - } -} - -module.exports = LocalStorageSession; diff --git a/src/lib/gramjs/sessions/Memory.js b/src/lib/gramjs/sessions/Memory.js deleted file mode 100644 index 550a2da45..000000000 --- a/src/lib/gramjs/sessions/Memory.js +++ /dev/null @@ -1,49 +0,0 @@ -const Session = require('./Abstract'); - -class MemorySession extends Session { - constructor() { - super(); - - this._serverAddress = undefined; - this._dcId = 0; - this._port = undefined; - this._takeoutId = undefined; - this._isTestServer = false; - - this._entities = new Set(); - this._updateStates = {}; - } - - get dcId() { - return this._dcId; - } - - get serverAddress() { - return this._serverAddress; - } - - get port() { - return this._port; - } - - get authKey() { - return this._authKey; - } - - set authKey(value) { - this._authKey = value; - } - - get isTestServer() { - return this._isTestServer; - } - - setDC(dcId, serverAddress, port, isTestServer) { - this._dcId = dcId | 0; - this._serverAddress = serverAddress; - this._port = port; - this._isTestServer = isTestServer; - } -} - -module.exports = MemorySession; diff --git a/src/lib/gramjs/sessions/Memory.ts b/src/lib/gramjs/sessions/Memory.ts new file mode 100644 index 000000000..96606e3f2 --- /dev/null +++ b/src/lib/gramjs/sessions/Memory.ts @@ -0,0 +1,67 @@ +import { AuthKey } from '../crypto/AuthKey'; +import Session from './Abstract'; + +// Dummy implementation +export default class MemorySession extends Session { + protected _serverAddress?: string; + + protected _dcId: number; + + protected _port?: number; + + protected _takeoutId: undefined; + + protected _entities: Set; + + protected _updateStates: {}; + + protected _isTestServer?: boolean; + + constructor() { + super(); + + this._serverAddress = undefined; + this._dcId = 0; + this._port = undefined; + this._takeoutId = undefined; + this._isTestServer = false; + + this._entities = new Set(); + this._updateStates = {}; + } + + get dcId() { + return this._dcId; + } + + get serverAddress() { + return this._serverAddress!; + } + + get port() { + return this._port!; + } + + get isTestServer() { + return this._isTestServer; + } + + setDC(dcId: number, serverAddress: string, port: number, isTestServer?: boolean) { + this._dcId = dcId | 0; + this._serverAddress = serverAddress; + this._port = port; + this._isTestServer = isTestServer; + } + + getAuthKey(dcId?: number | undefined): AuthKey { + return new AuthKey(); + } + + setAuthKey(authKey: AuthKey, dcId?: number) {} + + async load(): Promise { } + + save() {} + + delete() {} +} diff --git a/src/lib/gramjs/sessions/StorageSession.js b/src/lib/gramjs/sessions/StorageSession.js deleted file mode 100644 index 0d65657ce..000000000 --- a/src/lib/gramjs/sessions/StorageSession.js +++ /dev/null @@ -1,185 +0,0 @@ -const MemorySession = require('./Memory'); -const AuthKey = require('../crypto/AuthKey'); -const utils = require('../Utils'); - -const STORAGE_KEY_BASE = 'GramJs-session-'; -const SESSION_DATA_PREFIX = 'session:'; - -class StorageSession extends MemorySession { - constructor(sessionInfo) { - super(); - - this._authKeys = {}; - - if (sessionInfo && sessionInfo.startsWith(SESSION_DATA_PREFIX)) { - this._sessionString = sessionInfo; - } else if (sessionInfo) { - this._storageKey = sessionInfo; - } - } - - get authKey() { - throw new Error('Not supported'); - } - - set authKey(value) { - throw new Error('Not supported'); - } - - async load() { - if (this._sessionString) { - await this._loadFromSessionString(); - return; - } - - if (!this._storageKey) { - return; - } - - try { - const json = await this._fetchFromCache(); - const { - mainDcId, - keys, - hashes, - } = JSON.parse(json); - const { - ipAddress, - port, - } = utils.getDC(mainDcId); - - this.setDC(mainDcId, ipAddress, port, true); - - Object.keys(keys) - .forEach((dcId) => { - if (keys[dcId] && hashes[dcId]) { - this._authKeys[dcId] = new AuthKey( - Buffer.from(keys[dcId].data), - Buffer.from(hashes[dcId].data), - ); - } - }); - } catch (err) { - // eslint-disable-next-line no-console - console.warn('Failed to retrieve or parse session from storage'); - // eslint-disable-next-line no-console - console.warn(err); - } - } - - setDC(dcId, serverAddress, port, skipUpdateStorage = false) { - this._dcId = dcId; - this._serverAddress = serverAddress; - this._port = port; - - delete this._authKeys[dcId]; - - if (!skipUpdateStorage) { - void this._updateStorage(); - } - } - - async save() { - if (!this._storageKey) { - this._storageKey = generateStorageKey(); - } - - await this._updateStorage(); - - return this._storageKey; - } - - getAuthKey(dcId = this._dcId) { - return this._authKeys[dcId]; - } - - setAuthKey(authKey, dcId = this._dcId) { - this._authKeys[dcId] = authKey; - - void this._updateStorage(); - } - - getSessionData(asHex) { - const sessionData = { - mainDcId: this._dcId, - keys: {}, - hashes: {}, - }; - - Object - .keys(this._authKeys) - .forEach((dcId) => { - const authKey = this._authKeys[dcId]; - if (!authKey._key) return; - - sessionData.keys[dcId] = asHex ? authKey._key.toString('hex') : authKey._key; - sessionData.hashes[dcId] = asHex ? authKey._hash.toString('hex') : authKey._hash; - }); - - return sessionData; - } - - async _loadFromSessionString() { - const [, mainDcIdStr, mainDcKey] = this._sessionString.split(':'); - const mainDcId = Number(mainDcIdStr); - const { - ipAddress, - port, - } = utils.getDC(mainDcId); - this.setDC(mainDcId, ipAddress, port); - const authKey = new AuthKey(); - await authKey.setKey(Buffer.from(mainDcKey, 'hex'), true); - this.setAuthKey(authKey, mainDcId); - } - - async _updateStorage() { - if (!this._storageKey) { - return; - } - - try { - await this._saveToCache(JSON.stringify(this.getSessionData())); - } catch (err) { - // eslint-disable-next-line no-console - console.warn('Failed to update session in storage'); - // eslint-disable-next-line no-console - console.warn(err); - } - } - - async delete() { - try { - const deleted = await this._delete(); - return deleted; - } catch (err) { - // eslint-disable-next-line no-console - console.warn('Failed to delete session from storage'); - // eslint-disable-next-line no-console - console.warn(err); - } - return undefined; - } - - // @abstract - _delete() { - throw new Error('Not Implemented'); - } - - // @abstract - _fetchFromCache() { - throw new Error('Not Implemented'); - } - - // @abstract - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _saveToCache(data) { - throw new Error('Not Implemented'); - } -} - -function generateStorageKey() { - // Creating two sessions at the same moment is not expected nor supported. - return `${STORAGE_KEY_BASE}${Date.now()}`; -} - -module.exports = StorageSession; diff --git a/src/lib/gramjs/sessions/StringSession.js b/src/lib/gramjs/sessions/StringSession.js deleted file mode 100644 index 85dd4ecfa..000000000 --- a/src/lib/gramjs/sessions/StringSession.js +++ /dev/null @@ -1,105 +0,0 @@ -const MemorySession = require('./Memory'); -const AuthKey = require('../crypto/AuthKey'); -const BinaryReader = require('../extensions/BinaryReader'); - -const CURRENT_VERSION = '1'; - -class StringSession extends MemorySession { - /** - * This session file can be easily saved and loaded as a string. According - * to the initial design, it contains only the data that is necessary for - * successful connection and authentication, so takeout ID is not stored. - - * It is thought to be used where you don't want to create any on-disk - * files but would still like to be able to save and load existing sessions - * by other means. - - * You can use custom `encode` and `decode` functions, if present: - - * `encode` definition must be ``function encode(value: Buffer) -> string:``. - * `decode` definition must be ``function decode(value: string) -> Buffer:``. - * @param session {string|null} - */ - constructor(session = undefined) { - super(); - if (session) { - if (session[0] !== CURRENT_VERSION) { - throw new Error('Not a valid string'); - } - session = session.slice(1); - const r = StringSession.decode(session); - const reader = new BinaryReader(r); - this._dcId = reader.read(1) - .readUInt8(0); - const serverAddressLen = reader.read(2) - .readInt16BE(0); - this._serverAddress = String(reader.read(serverAddressLen)); - this._port = reader.read(2) - .readInt16BE(0); - this._key = reader.read(-1); - } - } - - /** - * @param x {Buffer} - * @returns {string} - */ - static encode(x) { - return x.toString('base64'); - } - - /** - * @param x {string} - * @returns {Buffer} - */ - static decode(x) { - return Buffer.from(x, 'base64'); - } - - async load() { - if (this._key) { - this._authKey = new AuthKey(); - await this._authKey.setKey(this._key); - } - } - - save() { - if (!this.authKey) { - return ''; - } - const dcBuffer = Buffer.from([this.dcId]); - const addressBuffer = Buffer.from(this.serverAddress); - const addressLengthBuffer = Buffer.alloc(2); - addressLengthBuffer.writeInt16BE(addressBuffer.length, 0); - const portBuffer = Buffer.alloc(2); - portBuffer.writeInt16BE(this.port, 0); - - return CURRENT_VERSION + StringSession.encode(Buffer.concat([ - dcBuffer, - addressLengthBuffer, - addressBuffer, - portBuffer, - this.authKey.getKey(), - ])); - } - - getAuthKey(dcId) { - if (dcId && dcId !== this.dcId) { - // Not supported. - return undefined; - } - - return this.authKey; - } - - setAuthKey(authKey, dcId) { - if (dcId && dcId !== this.dcId) { - // Not supported. - return; - } - - this.authKey = authKey; - } -} - -module.exports = StringSession; diff --git a/src/lib/gramjs/sessions/index.js b/src/lib/gramjs/sessions/index.js deleted file mode 100644 index 5b86708af..000000000 --- a/src/lib/gramjs/sessions/index.js +++ /dev/null @@ -1,15 +0,0 @@ -const Memory = require('./Memory'); -const StringSession = require('./StringSession'); -const CacheApiSession = require('./CacheApiSession'); -const LocalStorageSession = require('./LocalStorageSession'); -const IdbSession = require('./IdbSession'); -const CallbackSession = require('./CallbackSession'); - -module.exports = { - Memory, - StringSession, - CacheApiSession, - LocalStorageSession, - IdbSession, - CallbackSession, -}; diff --git a/src/lib/gramjs/sessions/index.ts b/src/lib/gramjs/sessions/index.ts new file mode 100644 index 000000000..9ce43b39c --- /dev/null +++ b/src/lib/gramjs/sessions/index.ts @@ -0,0 +1,7 @@ +import CallbackSession from './CallbackSession'; +import MemorySession from './Memory'; + +export { + CallbackSession, + MemorySession, +}; diff --git a/src/lib/gramjs/tl/AllTLObjects.js b/src/lib/gramjs/tl/AllTLObjects.js deleted file mode 100644 index 7465c0145..000000000 --- a/src/lib/gramjs/tl/AllTLObjects.js +++ /dev/null @@ -1,19 +0,0 @@ -const api = require('./api'); - -const LAYER = 197; -const tlobjects = {}; - -for (const tl of Object.values(api)) { - if (tl.CONSTRUCTOR_ID) { - tlobjects[tl.CONSTRUCTOR_ID] = tl; - } else { - for (const sub of Object.values(tl)) { - tlobjects[sub.CONSTRUCTOR_ID] = sub; - } - } -} - -module.exports = { - LAYER, - tlobjects, -}; diff --git a/src/lib/gramjs/tl/AllTLObjects.ts b/src/lib/gramjs/tl/AllTLObjects.ts new file mode 100644 index 000000000..1a4a3ffb8 --- /dev/null +++ b/src/lib/gramjs/tl/AllTLObjects.ts @@ -0,0 +1,16 @@ +import { Api } from '.'; + +const tlobjects: Record = {}; + +for (const tl of Object.values(Api)) { + if ('CONSTRUCTOR_ID' in tl) { + tlobjects[tl.CONSTRUCTOR_ID] = tl; + } else { + for (const sub of Object.values(tl)) { + tlobjects[sub.CONSTRUCTOR_ID] = sub; + } + } +} + +export const LAYER = 197; +export { tlobjects }; diff --git a/src/lib/gramjs/tl/MTProtoRequest.js b/src/lib/gramjs/tl/MTProtoRequest.js deleted file mode 100644 index e3fb80bd6..000000000 --- a/src/lib/gramjs/tl/MTProtoRequest.js +++ /dev/null @@ -1,48 +0,0 @@ -class MTProtoRequest { - constructor() { - this.sent = false; - this.msgId = 0; // long - this.sequence = 0; - - this.dirty = false; - this.sendTime = 0; - this.confirmReceived = false; - - // These should be overrode - - this.constructorId = 0; - this.confirmed = false; - this.responded = false; - } - - // these should not be overrode - onSendSuccess() { - this.sendTime = Date.now(); - this.sent = true; - } - - onConfirm() { - this.confirmReceived = true; - } - - needResend() { - return this.dirty || (this.confirmed && !this.confirmReceived && Date.now() - this.sendTime > 3000); - } - - // These should be overrode - onSend() { - throw Error(`Not overload ${this.constructor.name}`); - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - onResponse(buffer) { - throw Error(`Not overload ${this.constructor.name}`); - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - onException(exception) { - throw Error(`Not overload ${this.constructor.name}`); - } -} - -module.exports = MTProtoRequest; diff --git a/src/lib/gramjs/tl/MTProtoRequest.ts b/src/lib/gramjs/tl/MTProtoRequest.ts new file mode 100644 index 000000000..fa960d15b --- /dev/null +++ b/src/lib/gramjs/tl/MTProtoRequest.ts @@ -0,0 +1,56 @@ +export abstract class MTProtoRequest { + private sent: boolean; + + private sequence: number; + + private msgId: number; + + private readonly dirty: boolean; + + private sendTime: number; + + private confirmReceived: boolean; + + private constructorId: number; + + private readonly confirmed: boolean; + + private responded: boolean; + + constructor() { + this.sent = false; + this.msgId = 0; // long + this.sequence = 0; + + this.dirty = false; + this.sendTime = 0; + this.confirmReceived = false; + + // These should be overrode + + this.constructorId = 0; + this.confirmed = false; + this.responded = false; + } + + // These should not be overrode + onSendSuccess() { + this.sendTime = new Date().getTime(); + this.sent = true; + } + + onConfirm() { + this.confirmReceived = true; + } + + needResend() { + return this.dirty || (this.confirmed && !this.confirmReceived && new Date().getTime() - this.sendTime > 3000); + } + + // These should be overrode + abstract onSend(): void; + + abstract onResponse(_buffer: Buffer): void; + + abstract onException(_exception: Error): void; +} diff --git a/src/lib/gramjs/tl/api.d.ts b/src/lib/gramjs/tl/api.d.ts index 5396a71f6..340c2eeed 100644 --- a/src/lib/gramjs/tl/api.d.ts +++ b/src/lib/gramjs/tl/api.d.ts @@ -10,15 +10,17 @@ namespace Api { type AnyClass = new (...args: any[]) => any; type I = InstanceType; type ValuesOf = T[keyof T]; - type AnyLiteral = Record; + type AnyLiteral = Record | void; type Reader = any; // To be defined. type Client = any; // To be defined. type Utils = any; // To be defined. - type X = AnyLiteral; + type X = unknown; + type Type = unknown; type Bool = boolean; type int = number; + type double = number; type int128 = BigInteger; type int256 = BigInteger; type long = BigInteger; @@ -31,8 +33,6 @@ namespace Api { static classType: 'constructor' | 'request'; static serializeBytes(data: Buffer | string): Buffer; - static serializeDate(date: Date | number): Buffer; - static fromReader(reader: Reader): VirtualClass; getBytes(): Buffer; CONSTRUCTOR_ID: number; @@ -45,7 +45,6 @@ namespace Api { class Request extends VirtualClass> { static readResult(reader: Reader): Buffer; - static resolve(client: Client, utils: Utils): Promise; __response: Response; } @@ -669,27 +668,34 @@ namespace Api { export type TypeCollectibleInfo = fragment.CollectibleInfo; } - export class InputPeerEmpty extends VirtualClass {}; - export class InputPeerSelf extends VirtualClass {}; + export class InputPeerEmpty extends VirtualClass { + static fromReader(reader: Reader): InputPeerEmpty; + } + export class InputPeerSelf extends VirtualClass { + static fromReader(reader: Reader): InputPeerSelf; + } export class InputPeerChat extends VirtualClass<{ chatId: long; }> { chatId: long; - }; + static fromReader(reader: Reader): InputPeerChat; + } export class InputPeerUser extends VirtualClass<{ userId: long; accessHash: long; }> { userId: long; accessHash: long; - }; + static fromReader(reader: Reader): InputPeerUser; + } export class InputPeerChannel extends VirtualClass<{ channelId: long; accessHash: long; }> { channelId: long; accessHash: long; - }; + static fromReader(reader: Reader): InputPeerChannel; + } export class InputPeerUserFromMessage extends VirtualClass<{ peer: Api.TypeInputPeer; msgId: int; @@ -698,7 +704,8 @@ namespace Api { peer: Api.TypeInputPeer; msgId: int; userId: long; - }; + static fromReader(reader: Reader): InputPeerUserFromMessage; + } export class InputPeerChannelFromMessage extends VirtualClass<{ peer: Api.TypeInputPeer; msgId: int; @@ -707,16 +714,22 @@ namespace Api { peer: Api.TypeInputPeer; msgId: int; channelId: long; - }; - export class InputUserEmpty extends VirtualClass {}; - export class InputUserSelf extends VirtualClass {}; + static fromReader(reader: Reader): InputPeerChannelFromMessage; + } + export class InputUserEmpty extends VirtualClass { + static fromReader(reader: Reader): InputUserEmpty; + } + export class InputUserSelf extends VirtualClass { + static fromReader(reader: Reader): InputUserSelf; + } export class InputUser extends VirtualClass<{ userId: long; accessHash: long; }> { userId: long; accessHash: long; - }; + static fromReader(reader: Reader): InputUser; + } export class InputUserFromMessage extends VirtualClass<{ peer: Api.TypeInputPeer; msgId: int; @@ -725,7 +738,8 @@ namespace Api { peer: Api.TypeInputPeer; msgId: int; userId: long; - }; + static fromReader(reader: Reader): InputUserFromMessage; + } export class InputPhoneContact extends VirtualClass<{ clientId: long; phone: string; @@ -736,7 +750,8 @@ namespace Api { phone: string; firstName: string; lastName: string; - }; + static fromReader(reader: Reader): InputPhoneContact; + } export class InputFile extends VirtualClass<{ id: long; parts: int; @@ -747,7 +762,8 @@ namespace Api { parts: int; name: string; md5Checksum: string; - }; + static fromReader(reader: Reader): InputFile; + } export class InputFileBig extends VirtualClass<{ id: long; parts: int; @@ -756,42 +772,49 @@ namespace Api { id: long; parts: int; name: string; - }; + static fromReader(reader: Reader): InputFileBig; + } export class InputFileStoryDocument extends VirtualClass<{ id: Api.TypeInputDocument; }> { id: Api.TypeInputDocument; - }; - export class InputMediaEmpty extends VirtualClass {}; + static fromReader(reader: Reader): InputFileStoryDocument; + } + export class InputMediaEmpty extends VirtualClass { + static fromReader(reader: Reader): InputMediaEmpty; + } export class InputMediaUploadedPhoto extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; spoiler?: true; file: Api.TypeInputFile; stickers?: Api.TypeInputDocument[]; ttlSeconds?: int; }> { - // flags: undefined; + // flags: Api.Type; spoiler?: true; file: Api.TypeInputFile; stickers?: Api.TypeInputDocument[]; ttlSeconds?: int; - }; + static fromReader(reader: Reader): InputMediaUploadedPhoto; + } export class InputMediaPhoto extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; spoiler?: true; id: Api.TypeInputPhoto; ttlSeconds?: int; }> { - // flags: undefined; + // flags: Api.Type; spoiler?: true; id: Api.TypeInputPhoto; ttlSeconds?: int; - }; + static fromReader(reader: Reader): InputMediaPhoto; + } export class InputMediaGeoPoint extends VirtualClass<{ geoPoint: Api.TypeInputGeoPoint; }> { geoPoint: Api.TypeInputGeoPoint; - }; + static fromReader(reader: Reader): InputMediaGeoPoint; + } export class InputMediaContact extends VirtualClass<{ phoneNumber: string; firstName: string; @@ -802,9 +825,10 @@ namespace Api { firstName: string; lastName: string; vcard: string; - }; + static fromReader(reader: Reader): InputMediaContact; + } export class InputMediaUploadedDocument extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; nosoundVideo?: true; forceFile?: true; spoiler?: true; @@ -815,7 +839,7 @@ namespace Api { stickers?: Api.TypeInputDocument[]; ttlSeconds?: int; }> { - // flags: undefined; + // flags: Api.Type; nosoundVideo?: true; forceFile?: true; spoiler?: true; @@ -825,20 +849,22 @@ namespace Api { attributes: Api.TypeDocumentAttribute[]; stickers?: Api.TypeInputDocument[]; ttlSeconds?: int; - }; + static fromReader(reader: Reader): InputMediaUploadedDocument; + } export class InputMediaDocument extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; spoiler?: true; id: Api.TypeInputDocument; ttlSeconds?: int; query?: string; }> { - // flags: undefined; + // flags: Api.Type; spoiler?: true; id: Api.TypeInputDocument; ttlSeconds?: int; query?: string; - }; + static fromReader(reader: Reader): InputMediaDocument; + } export class InputMediaVenue extends VirtualClass<{ geoPoint: Api.TypeInputGeoPoint; title: string; @@ -853,36 +879,40 @@ namespace Api { provider: string; venueId: string; venueType: string; - }; + static fromReader(reader: Reader): InputMediaVenue; + } export class InputMediaPhotoExternal extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; spoiler?: true; url: string; ttlSeconds?: int; }> { - // flags: undefined; + // flags: Api.Type; spoiler?: true; url: string; ttlSeconds?: int; - }; + static fromReader(reader: Reader): InputMediaPhotoExternal; + } export class InputMediaDocumentExternal extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; spoiler?: true; url: string; ttlSeconds?: int; }> { - // flags: undefined; + // flags: Api.Type; spoiler?: true; url: string; ttlSeconds?: int; - }; + static fromReader(reader: Reader): InputMediaDocumentExternal; + } export class InputMediaGame extends VirtualClass<{ id: Api.TypeInputGame; }> { id: Api.TypeInputGame; - }; + static fromReader(reader: Reader): InputMediaGame; + } export class InputMediaInvoice extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; title: string; description: string; photo?: Api.TypeInputWebDocument; @@ -893,7 +923,7 @@ namespace Api { startParam?: string; extendedMedia?: Api.TypeInputMedia; }> { - // flags: undefined; + // flags: Api.Type; title: string; description: string; photo?: Api.TypeInputWebDocument; @@ -903,103 +933,119 @@ namespace Api { providerData: Api.TypeDataJSON; startParam?: string; extendedMedia?: Api.TypeInputMedia; - }; + static fromReader(reader: Reader): InputMediaInvoice; + } export class InputMediaGeoLive extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; stopped?: true; geoPoint: Api.TypeInputGeoPoint; heading?: int; period?: int; proximityNotificationRadius?: int; }> { - // flags: undefined; + // flags: Api.Type; stopped?: true; geoPoint: Api.TypeInputGeoPoint; heading?: int; period?: int; proximityNotificationRadius?: int; - }; + static fromReader(reader: Reader): InputMediaGeoLive; + } export class InputMediaPoll extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; poll: Api.TypePoll; correctAnswers?: bytes[]; solution?: string; solutionEntities?: Api.TypeMessageEntity[]; }> { - // flags: undefined; + // flags: Api.Type; poll: Api.TypePoll; correctAnswers?: bytes[]; solution?: string; solutionEntities?: Api.TypeMessageEntity[]; - }; + static fromReader(reader: Reader): InputMediaPoll; + } export class InputMediaDice extends VirtualClass<{ emoticon: string; }> { emoticon: string; - }; + static fromReader(reader: Reader): InputMediaDice; + } export class InputMediaStory extends VirtualClass<{ peer: Api.TypeInputPeer; id: int; }> { peer: Api.TypeInputPeer; id: int; - }; + static fromReader(reader: Reader): InputMediaStory; + } export class InputMediaWebPage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; forceLargeMedia?: true; forceSmallMedia?: true; optional?: true; url: string; }> { - // flags: undefined; + // flags: Api.Type; forceLargeMedia?: true; forceSmallMedia?: true; optional?: true; url: string; - }; + static fromReader(reader: Reader): InputMediaWebPage; + } export class InputMediaPaidMedia extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; starsAmount: long; extendedMedia: Api.TypeInputMedia[]; payload?: string; }> { - // flags: undefined; + // flags: Api.Type; starsAmount: long; extendedMedia: Api.TypeInputMedia[]; payload?: string; - }; - export class InputChatPhotoEmpty extends VirtualClass {}; + static fromReader(reader: Reader): InputMediaPaidMedia; + } + export class InputChatPhotoEmpty extends VirtualClass { + static fromReader(reader: Reader): InputChatPhotoEmpty; + } export class InputChatUploadedPhoto extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; file?: Api.TypeInputFile; video?: Api.TypeInputFile; videoStartTs?: double; videoEmojiMarkup?: Api.TypeVideoSize; } | void> { - // flags: undefined; + // flags: Api.Type; file?: Api.TypeInputFile; video?: Api.TypeInputFile; videoStartTs?: double; videoEmojiMarkup?: Api.TypeVideoSize; - }; + static fromReader(reader: Reader): InputChatUploadedPhoto; + } export class InputChatPhoto extends VirtualClass<{ id: Api.TypeInputPhoto; }> { id: Api.TypeInputPhoto; - }; - export class InputGeoPointEmpty extends VirtualClass {}; + static fromReader(reader: Reader): InputChatPhoto; + } + export class InputGeoPointEmpty extends VirtualClass { + static fromReader(reader: Reader): InputGeoPointEmpty; + } export class InputGeoPoint extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; lat: double; long: double; accuracyRadius?: int; }> { - // flags: undefined; + // flags: Api.Type; lat: double; long: double; accuracyRadius?: int; - }; - export class InputPhotoEmpty extends VirtualClass {}; + static fromReader(reader: Reader): InputGeoPoint; + } + export class InputPhotoEmpty extends VirtualClass { + static fromReader(reader: Reader): InputPhotoEmpty; + } export class InputPhoto extends VirtualClass<{ id: long; accessHash: long; @@ -1008,7 +1054,8 @@ namespace Api { id: long; accessHash: long; fileReference: bytes; - }; + static fromReader(reader: Reader): InputPhoto; + } export class InputFileLocation extends VirtualClass<{ volumeId: long; localId: int; @@ -1019,14 +1066,16 @@ namespace Api { localId: int; secret: long; fileReference: bytes; - }; + static fromReader(reader: Reader): InputFileLocation; + } export class InputEncryptedFileLocation extends VirtualClass<{ id: long; accessHash: long; }> { id: long; accessHash: long; - }; + static fromReader(reader: Reader): InputEncryptedFileLocation; + } export class InputDocumentFileLocation extends VirtualClass<{ id: long; accessHash: long; @@ -1037,15 +1086,19 @@ namespace Api { accessHash: long; fileReference: bytes; thumbSize: string; - }; + static fromReader(reader: Reader): InputDocumentFileLocation; + } export class InputSecureFileLocation extends VirtualClass<{ id: long; accessHash: long; }> { id: long; accessHash: long; - }; - export class InputTakeoutFileLocation extends VirtualClass {}; + static fromReader(reader: Reader): InputSecureFileLocation; + } + export class InputTakeoutFileLocation extends VirtualClass { + static fromReader(reader: Reader): InputTakeoutFileLocation; + } export class InputPhotoFileLocation extends VirtualClass<{ id: long; accessHash: long; @@ -1056,7 +1109,8 @@ namespace Api { accessHash: long; fileReference: bytes; thumbSize: string; - }; + static fromReader(reader: Reader): InputPhotoFileLocation; + } export class InputPhotoLegacyFileLocation extends VirtualClass<{ id: long; accessHash: long; @@ -1071,62 +1125,70 @@ namespace Api { volumeId: long; localId: int; secret: long; - }; + static fromReader(reader: Reader): InputPhotoLegacyFileLocation; + } export class InputPeerPhotoFileLocation extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; big?: true; peer: Api.TypeInputPeer; photoId: long; }> { - // flags: undefined; + // flags: Api.Type; big?: true; peer: Api.TypeInputPeer; photoId: long; - }; + static fromReader(reader: Reader): InputPeerPhotoFileLocation; + } export class InputStickerSetThumb extends VirtualClass<{ stickerset: Api.TypeInputStickerSet; thumbVersion: int; }> { stickerset: Api.TypeInputStickerSet; thumbVersion: int; - }; + static fromReader(reader: Reader): InputStickerSetThumb; + } export class InputGroupCallStream extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; call: Api.TypeInputGroupCall; timeMs: long; scale: int; videoChannel?: int; videoQuality?: int; }> { - // flags: undefined; + // flags: Api.Type; call: Api.TypeInputGroupCall; timeMs: long; scale: int; videoChannel?: int; videoQuality?: int; - }; + static fromReader(reader: Reader): InputGroupCallStream; + } export class PeerUser extends VirtualClass<{ userId: long; }> { userId: long; - }; + static fromReader(reader: Reader): PeerUser; + } export class PeerChat extends VirtualClass<{ chatId: long; }> { chatId: long; - }; + static fromReader(reader: Reader): PeerChat; + } export class PeerChannel extends VirtualClass<{ channelId: long; }> { channelId: long; - }; + static fromReader(reader: Reader): PeerChannel; + } export class UserEmpty extends VirtualClass<{ id: long; }> { id: long; - }; + static fromReader(reader: Reader): UserEmpty; + } export class User extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; self?: true; contact?: true; mutualContact?: true; @@ -1145,7 +1207,7 @@ namespace Api { botAttachMenu?: true; premium?: true; attachMenuEnabled?: true; - // flags2: undefined; + // flags2: Api.Type; botCanEdit?: true; closeFriend?: true; storiesHidden?: true; @@ -1173,7 +1235,7 @@ namespace Api { botActiveUsers?: int; botVerificationIcon?: long; }> { - // flags: undefined; + // flags: Api.Type; self?: true; contact?: true; mutualContact?: true; @@ -1192,7 +1254,7 @@ namespace Api { botAttachMenu?: true; premium?: true; attachMenuEnabled?: true; - // flags2: undefined; + // flags2: Api.Type; botCanEdit?: true; closeFriend?: true; storiesHidden?: true; @@ -1219,62 +1281,74 @@ namespace Api { profileColor?: Api.TypePeerColor; botActiveUsers?: int; botVerificationIcon?: long; - }; - export class UserProfilePhotoEmpty extends VirtualClass {}; + static fromReader(reader: Reader): User; + } + export class UserProfilePhotoEmpty extends VirtualClass { + static fromReader(reader: Reader): UserProfilePhotoEmpty; + } export class UserProfilePhoto extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; hasVideo?: true; personal?: true; photoId: long; strippedThumb?: bytes; dcId: int; }> { - // flags: undefined; + // flags: Api.Type; hasVideo?: true; personal?: true; photoId: long; strippedThumb?: bytes; dcId: int; - }; - export class UserStatusEmpty extends VirtualClass {}; + static fromReader(reader: Reader): UserProfilePhoto; + } + export class UserStatusEmpty extends VirtualClass { + static fromReader(reader: Reader): UserStatusEmpty; + } export class UserStatusOnline extends VirtualClass<{ expires: int; }> { expires: int; - }; + static fromReader(reader: Reader): UserStatusOnline; + } export class UserStatusOffline extends VirtualClass<{ wasOnline: int; }> { wasOnline: int; - }; + static fromReader(reader: Reader): UserStatusOffline; + } export class UserStatusRecently extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; byMe?: true; } | void> { - // flags: undefined; + // flags: Api.Type; byMe?: true; - }; + static fromReader(reader: Reader): UserStatusRecently; + } export class UserStatusLastWeek extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; byMe?: true; } | void> { - // flags: undefined; + // flags: Api.Type; byMe?: true; - }; + static fromReader(reader: Reader): UserStatusLastWeek; + } export class UserStatusLastMonth extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; byMe?: true; } | void> { - // flags: undefined; + // flags: Api.Type; byMe?: true; - }; + static fromReader(reader: Reader): UserStatusLastMonth; + } export class ChatEmpty extends VirtualClass<{ id: long; }> { id: long; - }; + static fromReader(reader: Reader): ChatEmpty; + } export class Chat extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; creator?: true; left?: true; deactivated?: true; @@ -1291,7 +1365,7 @@ namespace Api { adminRights?: Api.TypeChatAdminRights; defaultBannedRights?: Api.TypeChatBannedRights; }> { - // flags: undefined; + // flags: Api.Type; creator?: true; left?: true; deactivated?: true; @@ -1307,16 +1381,18 @@ namespace Api { migratedTo?: Api.TypeInputChannel; adminRights?: Api.TypeChatAdminRights; defaultBannedRights?: Api.TypeChatBannedRights; - }; + static fromReader(reader: Reader): Chat; + } export class ChatForbidden extends VirtualClass<{ id: long; title: string; }> { id: long; title: string; - }; + static fromReader(reader: Reader): ChatForbidden; + } export class Channel extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; creator?: true; left?: true; broadcast?: true; @@ -1337,7 +1413,7 @@ namespace Api { joinToSend?: true; joinRequest?: true; forum?: true; - // flags2: undefined; + // flags2: Api.Type; storiesHidden?: true; storiesHiddenMin?: true; storiesUnavailable?: true; @@ -1362,7 +1438,7 @@ namespace Api { subscriptionUntilDate?: int; botVerificationIcon?: long; }> { - // flags: undefined; + // flags: Api.Type; creator?: true; left?: true; broadcast?: true; @@ -1383,7 +1459,7 @@ namespace Api { joinToSend?: true; joinRequest?: true; forum?: true; - // flags2: undefined; + // flags2: Api.Type; storiesHidden?: true; storiesHiddenMin?: true; storiesUnavailable?: true; @@ -1407,9 +1483,10 @@ namespace Api { level?: int; subscriptionUntilDate?: int; botVerificationIcon?: long; - }; + static fromReader(reader: Reader): Channel; + } export class ChannelForbidden extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; broadcast?: true; megagroup?: true; id: long; @@ -1417,16 +1494,17 @@ namespace Api { title: string; untilDate?: int; }> { - // flags: undefined; + // flags: Api.Type; broadcast?: true; megagroup?: true; id: long; accessHash: long; title: string; untilDate?: int; - }; + static fromReader(reader: Reader): ChannelForbidden; + } export class ChatFull extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; canSetUsername?: true; hasScheduled?: true; translationsDisabled?: true; @@ -1448,7 +1526,7 @@ namespace Api { availableReactions?: Api.TypeChatReactions; reactionsLimit?: int; }> { - // flags: undefined; + // flags: Api.Type; canSetUsername?: true; hasScheduled?: true; translationsDisabled?: true; @@ -1469,9 +1547,10 @@ namespace Api { recentRequesters?: long[]; availableReactions?: Api.TypeChatReactions; reactionsLimit?: int; - }; + static fromReader(reader: Reader): ChatFull; + } export class ChannelFull extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; canViewParticipants?: true; canSetUsername?: true; canSetStickers?: true; @@ -1480,7 +1559,7 @@ namespace Api { hasScheduled?: true; canViewStats?: true; blocked?: true; - // flags2: undefined; + // flags2: Api.Type; canDeleteChannel?: true; antispam?: true; participantsHidden?: true; @@ -1535,7 +1614,7 @@ namespace Api { emojiset?: Api.TypeStickerSet; botVerification?: Api.TypeBotVerification; }> { - // flags: undefined; + // flags: Api.Type; canViewParticipants?: true; canSetUsername?: true; canSetStickers?: true; @@ -1544,7 +1623,7 @@ namespace Api { hasScheduled?: true; canViewStats?: true; blocked?: true; - // flags2: undefined; + // flags2: Api.Type; canDeleteChannel?: true; antispam?: true; participantsHidden?: true; @@ -1598,7 +1677,8 @@ namespace Api { boostsUnrestrict?: int; emojiset?: Api.TypeStickerSet; botVerification?: Api.TypeBotVerification; - }; + static fromReader(reader: Reader): ChannelFull; + } export class ChatParticipant extends VirtualClass<{ userId: long; inviterId: long; @@ -1607,12 +1687,14 @@ namespace Api { userId: long; inviterId: long; date: int; - }; + static fromReader(reader: Reader): ChatParticipant; + } export class ChatParticipantCreator extends VirtualClass<{ userId: long; }> { userId: long; - }; + static fromReader(reader: Reader): ChatParticipantCreator; + } export class ChatParticipantAdmin extends VirtualClass<{ userId: long; inviterId: long; @@ -1621,16 +1703,18 @@ namespace Api { userId: long; inviterId: long; date: int; - }; + static fromReader(reader: Reader): ChatParticipantAdmin; + } export class ChatParticipantsForbidden extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; chatId: long; selfParticipant?: Api.TypeChatParticipant; }> { - // flags: undefined; + // flags: Api.Type; chatId: long; selfParticipant?: Api.TypeChatParticipant; - }; + static fromReader(reader: Reader): ChatParticipantsForbidden; + } export class ChatParticipants extends VirtualClass<{ chatId: long; participants: Api.TypeChatParticipant[]; @@ -1639,32 +1723,37 @@ namespace Api { chatId: long; participants: Api.TypeChatParticipant[]; version: int; - }; - export class ChatPhotoEmpty extends VirtualClass {}; + static fromReader(reader: Reader): ChatParticipants; + } + export class ChatPhotoEmpty extends VirtualClass { + static fromReader(reader: Reader): ChatPhotoEmpty; + } export class ChatPhoto extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; hasVideo?: true; photoId: long; strippedThumb?: bytes; dcId: int; }> { - // flags: undefined; + // flags: Api.Type; hasVideo?: true; photoId: long; strippedThumb?: bytes; dcId: int; - }; + static fromReader(reader: Reader): ChatPhoto; + } export class MessageEmpty extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; id: int; peerId?: Api.TypePeer; }> { - // flags: undefined; + // flags: Api.Type; id: int; peerId?: Api.TypePeer; - }; + static fromReader(reader: Reader): MessageEmpty; + } export class Message extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; out?: true; mentioned?: true; mediaUnread?: true; @@ -1676,7 +1765,7 @@ namespace Api { pinned?: true; noforwards?: true; invertMedia?: true; - // flags2: undefined; + // flags2: Api.Type; offline?: true; videoProcessingPending?: true; id: int; @@ -1707,7 +1796,7 @@ namespace Api { factcheck?: Api.TypeFactCheck; reportDeliveryUntilDate?: int; }> { - // flags: undefined; + // flags: Api.Type; out?: true; mentioned?: true; mediaUnread?: true; @@ -1719,7 +1808,7 @@ namespace Api { pinned?: true; noforwards?: true; invertMedia?: true; - // flags2: undefined; + // flags2: Api.Type; offline?: true; videoProcessingPending?: true; id: int; @@ -1749,9 +1838,10 @@ namespace Api { effect?: long; factcheck?: Api.TypeFactCheck; reportDeliveryUntilDate?: int; - }; + static fromReader(reader: Reader): Message; + } export class MessageService extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; out?: true; mentioned?: true; mediaUnread?: true; @@ -1768,7 +1858,7 @@ namespace Api { reactions?: Api.TypeMessageReactions; ttlPeriod?: int; }> { - // flags: undefined; + // flags: Api.Type; out?: true; mentioned?: true; mediaUnread?: true; @@ -1784,24 +1874,29 @@ namespace Api { action: Api.TypeMessageAction; reactions?: Api.TypeMessageReactions; ttlPeriod?: int; - }; - export class MessageMediaEmpty extends VirtualClass {}; + static fromReader(reader: Reader): MessageService; + } + export class MessageMediaEmpty extends VirtualClass { + static fromReader(reader: Reader): MessageMediaEmpty; + } export class MessageMediaPhoto extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; spoiler?: true; photo?: Api.TypePhoto; ttlSeconds?: int; } | void> { - // flags: undefined; + // flags: Api.Type; spoiler?: true; photo?: Api.TypePhoto; ttlSeconds?: int; - }; + static fromReader(reader: Reader): MessageMediaPhoto; + } export class MessageMediaGeo extends VirtualClass<{ geo: Api.TypeGeoPoint; }> { geo: Api.TypeGeoPoint; - }; + static fromReader(reader: Reader): MessageMediaGeo; + } export class MessageMediaContact extends VirtualClass<{ phoneNumber: string; firstName: string; @@ -1814,10 +1909,13 @@ namespace Api { lastName: string; vcard: string; userId: long; - }; - export class MessageMediaUnsupported extends VirtualClass {}; + static fromReader(reader: Reader): MessageMediaContact; + } + export class MessageMediaUnsupported extends VirtualClass { + static fromReader(reader: Reader): MessageMediaUnsupported; + } export class MessageMediaDocument extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; nopremium?: true; spoiler?: true; video?: true; @@ -1827,7 +1925,7 @@ namespace Api { altDocuments?: Api.TypeDocument[]; ttlSeconds?: int; } | void> { - // flags: undefined; + // flags: Api.Type; nopremium?: true; spoiler?: true; video?: true; @@ -1836,22 +1934,24 @@ namespace Api { document?: Api.TypeDocument; altDocuments?: Api.TypeDocument[]; ttlSeconds?: int; - }; + static fromReader(reader: Reader): MessageMediaDocument; + } export class MessageMediaWebPage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; forceLargeMedia?: true; forceSmallMedia?: true; manual?: true; safe?: true; webpage: Api.TypeWebPage; }> { - // flags: undefined; + // flags: Api.Type; forceLargeMedia?: true; forceSmallMedia?: true; manual?: true; safe?: true; webpage: Api.TypeWebPage; - }; + static fromReader(reader: Reader): MessageMediaWebPage; + } export class MessageMediaVenue extends VirtualClass<{ geo: Api.TypeGeoPoint; title: string; @@ -1866,14 +1966,16 @@ namespace Api { provider: string; venueId: string; venueType: string; - }; + static fromReader(reader: Reader): MessageMediaVenue; + } export class MessageMediaGame extends VirtualClass<{ game: Api.TypeGame; }> { game: Api.TypeGame; - }; + static fromReader(reader: Reader): MessageMediaGame; + } export class MessageMediaInvoice extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; shippingAddressRequested?: true; test?: true; title: string; @@ -1885,7 +1987,7 @@ namespace Api { startParam: string; extendedMedia?: Api.TypeMessageExtendedMedia; }> { - // flags: undefined; + // flags: Api.Type; shippingAddressRequested?: true; test?: true; title: string; @@ -1896,49 +1998,54 @@ namespace Api { totalAmount: long; startParam: string; extendedMedia?: Api.TypeMessageExtendedMedia; - }; + static fromReader(reader: Reader): MessageMediaInvoice; + } export class MessageMediaGeoLive extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; geo: Api.TypeGeoPoint; heading?: int; period: int; proximityNotificationRadius?: int; }> { - // flags: undefined; + // flags: Api.Type; geo: Api.TypeGeoPoint; heading?: int; period: int; proximityNotificationRadius?: int; - }; + static fromReader(reader: Reader): MessageMediaGeoLive; + } export class MessageMediaPoll extends VirtualClass<{ poll: Api.TypePoll; results: Api.TypePollResults; }> { poll: Api.TypePoll; results: Api.TypePollResults; - }; + static fromReader(reader: Reader): MessageMediaPoll; + } export class MessageMediaDice extends VirtualClass<{ value: int; emoticon: string; }> { value: int; emoticon: string; - }; + static fromReader(reader: Reader): MessageMediaDice; + } export class MessageMediaStory extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; viaMention?: true; peer: Api.TypePeer; id: int; story?: Api.TypeStoryItem; }> { - // flags: undefined; + // flags: Api.Type; viaMention?: true; peer: Api.TypePeer; id: int; story?: Api.TypeStoryItem; - }; + static fromReader(reader: Reader): MessageMediaStory; + } export class MessageMediaGiveaway extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; onlyNewSubscribers?: true; winnersAreVisible?: true; channels: long[]; @@ -1949,7 +2056,7 @@ namespace Api { stars?: long; untilDate: int; }> { - // flags: undefined; + // flags: Api.Type; onlyNewSubscribers?: true; winnersAreVisible?: true; channels: long[]; @@ -1959,9 +2066,10 @@ namespace Api { months?: int; stars?: long; untilDate: int; - }; + static fromReader(reader: Reader): MessageMediaGiveaway; + } export class MessageMediaGiveawayResults extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; onlyNewSubscribers?: true; refunded?: true; channelId: long; @@ -1975,7 +2083,7 @@ namespace Api { prizeDescription?: string; untilDate: int; }> { - // flags: undefined; + // flags: Api.Type; onlyNewSubscribers?: true; refunded?: true; channelId: long; @@ -1988,76 +2096,96 @@ namespace Api { stars?: long; prizeDescription?: string; untilDate: int; - }; + static fromReader(reader: Reader): MessageMediaGiveawayResults; + } export class MessageMediaPaidMedia extends VirtualClass<{ starsAmount: long; extendedMedia: Api.TypeMessageExtendedMedia[]; }> { starsAmount: long; extendedMedia: Api.TypeMessageExtendedMedia[]; - }; - export class MessageActionEmpty extends VirtualClass {}; + static fromReader(reader: Reader): MessageMediaPaidMedia; + } + export class MessageActionEmpty extends VirtualClass { + static fromReader(reader: Reader): MessageActionEmpty; + } export class MessageActionChatCreate extends VirtualClass<{ title: string; users: long[]; }> { title: string; users: long[]; - }; + static fromReader(reader: Reader): MessageActionChatCreate; + } export class MessageActionChatEditTitle extends VirtualClass<{ title: string; }> { title: string; - }; + static fromReader(reader: Reader): MessageActionChatEditTitle; + } export class MessageActionChatEditPhoto extends VirtualClass<{ photo: Api.TypePhoto; }> { photo: Api.TypePhoto; - }; - export class MessageActionChatDeletePhoto extends VirtualClass {}; + static fromReader(reader: Reader): MessageActionChatEditPhoto; + } + export class MessageActionChatDeletePhoto extends VirtualClass { + static fromReader(reader: Reader): MessageActionChatDeletePhoto; + } export class MessageActionChatAddUser extends VirtualClass<{ users: long[]; }> { users: long[]; - }; + static fromReader(reader: Reader): MessageActionChatAddUser; + } export class MessageActionChatDeleteUser extends VirtualClass<{ userId: long; }> { userId: long; - }; + static fromReader(reader: Reader): MessageActionChatDeleteUser; + } export class MessageActionChatJoinedByLink extends VirtualClass<{ inviterId: long; }> { inviterId: long; - }; + static fromReader(reader: Reader): MessageActionChatJoinedByLink; + } export class MessageActionChannelCreate extends VirtualClass<{ title: string; }> { title: string; - }; + static fromReader(reader: Reader): MessageActionChannelCreate; + } export class MessageActionChatMigrateTo extends VirtualClass<{ channelId: long; }> { channelId: long; - }; + static fromReader(reader: Reader): MessageActionChatMigrateTo; + } export class MessageActionChannelMigrateFrom extends VirtualClass<{ title: string; chatId: long; }> { title: string; chatId: long; - }; - export class MessageActionPinMessage extends VirtualClass {}; - export class MessageActionHistoryClear extends VirtualClass {}; + static fromReader(reader: Reader): MessageActionChannelMigrateFrom; + } + export class MessageActionPinMessage extends VirtualClass { + static fromReader(reader: Reader): MessageActionPinMessage; + } + export class MessageActionHistoryClear extends VirtualClass { + static fromReader(reader: Reader): MessageActionHistoryClear; + } export class MessageActionGameScore extends VirtualClass<{ gameId: long; score: int; }> { gameId: long; score: int; - }; + static fromReader(reader: Reader): MessageActionGameScore; + } export class MessageActionPaymentSentMe extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; recurringInit?: true; recurringUsed?: true; currency: string; @@ -2068,7 +2196,7 @@ namespace Api { charge: Api.TypePaymentCharge; subscriptionUntilDate?: int; }> { - // flags: undefined; + // flags: Api.Type; recurringInit?: true; recurringUsed?: true; currency: string; @@ -2078,9 +2206,10 @@ namespace Api { shippingOptionId?: string; charge: Api.TypePaymentCharge; subscriptionUntilDate?: int; - }; + static fromReader(reader: Reader): MessageActionPaymentSentMe; + } export class MessageActionPaymentSent extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; recurringInit?: true; recurringUsed?: true; currency: string; @@ -2088,59 +2217,69 @@ namespace Api { invoiceSlug?: string; subscriptionUntilDate?: int; }> { - // flags: undefined; + // flags: Api.Type; recurringInit?: true; recurringUsed?: true; currency: string; totalAmount: long; invoiceSlug?: string; subscriptionUntilDate?: int; - }; + static fromReader(reader: Reader): MessageActionPaymentSent; + } export class MessageActionPhoneCall extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; video?: true; callId: long; reason?: Api.TypePhoneCallDiscardReason; duration?: int; }> { - // flags: undefined; + // flags: Api.Type; video?: true; callId: long; reason?: Api.TypePhoneCallDiscardReason; duration?: int; - }; - export class MessageActionScreenshotTaken extends VirtualClass {}; + static fromReader(reader: Reader): MessageActionPhoneCall; + } + export class MessageActionScreenshotTaken extends VirtualClass { + static fromReader(reader: Reader): MessageActionScreenshotTaken; + } export class MessageActionCustomAction extends VirtualClass<{ message: string; }> { message: string; - }; + static fromReader(reader: Reader): MessageActionCustomAction; + } export class MessageActionBotAllowed extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; attachMenu?: true; fromRequest?: true; domain?: string; app?: Api.TypeBotApp; } | void> { - // flags: undefined; + // flags: Api.Type; attachMenu?: true; fromRequest?: true; domain?: string; app?: Api.TypeBotApp; - }; + static fromReader(reader: Reader): MessageActionBotAllowed; + } export class MessageActionSecureValuesSentMe extends VirtualClass<{ values: Api.TypeSecureValue[]; credentials: Api.TypeSecureCredentialsEncrypted; }> { values: Api.TypeSecureValue[]; credentials: Api.TypeSecureCredentialsEncrypted; - }; + static fromReader(reader: Reader): MessageActionSecureValuesSentMe; + } export class MessageActionSecureValuesSent extends VirtualClass<{ types: Api.TypeSecureValueType[]; }> { types: Api.TypeSecureValueType[]; - }; - export class MessageActionContactSignUp extends VirtualClass {}; + static fromReader(reader: Reader): MessageActionSecureValuesSent; + } + export class MessageActionContactSignUp extends VirtualClass { + static fromReader(reader: Reader): MessageActionContactSignUp; + } export class MessageActionGeoProximityReached extends VirtualClass<{ fromId: Api.TypePeer; toId: Api.TypePeer; @@ -2149,59 +2288,69 @@ namespace Api { fromId: Api.TypePeer; toId: Api.TypePeer; distance: int; - }; + static fromReader(reader: Reader): MessageActionGeoProximityReached; + } export class MessageActionGroupCall extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; call: Api.TypeInputGroupCall; duration?: int; }> { - // flags: undefined; + // flags: Api.Type; call: Api.TypeInputGroupCall; duration?: int; - }; + static fromReader(reader: Reader): MessageActionGroupCall; + } export class MessageActionInviteToGroupCall extends VirtualClass<{ call: Api.TypeInputGroupCall; users: long[]; }> { call: Api.TypeInputGroupCall; users: long[]; - }; + static fromReader(reader: Reader): MessageActionInviteToGroupCall; + } export class MessageActionSetMessagesTTL extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; period: int; autoSettingFrom?: long; }> { - // flags: undefined; + // flags: Api.Type; period: int; autoSettingFrom?: long; - }; + static fromReader(reader: Reader): MessageActionSetMessagesTTL; + } export class MessageActionGroupCallScheduled extends VirtualClass<{ call: Api.TypeInputGroupCall; scheduleDate: int; }> { call: Api.TypeInputGroupCall; scheduleDate: int; - }; + static fromReader(reader: Reader): MessageActionGroupCallScheduled; + } export class MessageActionSetChatTheme extends VirtualClass<{ emoticon: string; }> { emoticon: string; - }; - export class MessageActionChatJoinedByRequest extends VirtualClass {}; + static fromReader(reader: Reader): MessageActionSetChatTheme; + } + export class MessageActionChatJoinedByRequest extends VirtualClass { + static fromReader(reader: Reader): MessageActionChatJoinedByRequest; + } export class MessageActionWebViewDataSentMe extends VirtualClass<{ text: string; data: string; }> { text: string; data: string; - }; + static fromReader(reader: Reader): MessageActionWebViewDataSentMe; + } export class MessageActionWebViewDataSent extends VirtualClass<{ text: string; }> { text: string; - }; + static fromReader(reader: Reader): MessageActionWebViewDataSent; + } export class MessageActionGiftPremium extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; currency: string; amount: long; months: int; @@ -2209,63 +2358,69 @@ namespace Api { cryptoAmount?: long; message?: Api.TypeTextWithEntities; }> { - // flags: undefined; + // flags: Api.Type; currency: string; amount: long; months: int; cryptoCurrency?: string; cryptoAmount?: long; message?: Api.TypeTextWithEntities; - }; + static fromReader(reader: Reader): MessageActionGiftPremium; + } export class MessageActionTopicCreate extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; title: string; iconColor: int; iconEmojiId?: long; }> { - // flags: undefined; + // flags: Api.Type; title: string; iconColor: int; iconEmojiId?: long; - }; + static fromReader(reader: Reader): MessageActionTopicCreate; + } export class MessageActionTopicEdit extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; title?: string; iconEmojiId?: long; closed?: Bool; hidden?: Bool; } | void> { - // flags: undefined; + // flags: Api.Type; title?: string; iconEmojiId?: long; closed?: Bool; hidden?: Bool; - }; + static fromReader(reader: Reader): MessageActionTopicEdit; + } export class MessageActionSuggestProfilePhoto extends VirtualClass<{ photo: Api.TypePhoto; }> { photo: Api.TypePhoto; - }; + static fromReader(reader: Reader): MessageActionSuggestProfilePhoto; + } export class MessageActionRequestedPeer extends VirtualClass<{ buttonId: int; peers: Api.TypePeer[]; }> { buttonId: int; peers: Api.TypePeer[]; - }; + static fromReader(reader: Reader): MessageActionRequestedPeer; + } export class MessageActionSetChatWallPaper extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; same?: true; forBoth?: true; wallpaper: Api.TypeWallPaper; }> { - // flags: undefined; + // flags: Api.Type; same?: true; forBoth?: true; wallpaper: Api.TypeWallPaper; - }; + static fromReader(reader: Reader): MessageActionSetChatWallPaper; + } export class MessageActionGiftCode extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; viaGiveaway?: true; unclaimed?: true; boostPeer?: Api.TypePeer; @@ -2277,7 +2432,7 @@ namespace Api { cryptoAmount?: long; message?: Api.TypeTextWithEntities; }> { - // flags: undefined; + // flags: Api.Type; viaGiveaway?: true; unclaimed?: true; boostPeer?: Api.TypePeer; @@ -2288,54 +2443,60 @@ namespace Api { cryptoCurrency?: string; cryptoAmount?: long; message?: Api.TypeTextWithEntities; - }; + static fromReader(reader: Reader): MessageActionGiftCode; + } export class MessageActionGiveawayLaunch extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; stars?: long; } | void> { - // flags: undefined; + // flags: Api.Type; stars?: long; - }; + static fromReader(reader: Reader): MessageActionGiveawayLaunch; + } export class MessageActionGiveawayResults extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; stars?: true; winnersCount: int; unclaimedCount: int; }> { - // flags: undefined; + // flags: Api.Type; stars?: true; winnersCount: int; unclaimedCount: int; - }; + static fromReader(reader: Reader): MessageActionGiveawayResults; + } export class MessageActionBoostApply extends VirtualClass<{ boosts: int; }> { boosts: int; - }; + static fromReader(reader: Reader): MessageActionBoostApply; + } export class MessageActionRequestedPeerSentMe extends VirtualClass<{ buttonId: int; peers: Api.TypeRequestedPeer[]; }> { buttonId: int; peers: Api.TypeRequestedPeer[]; - }; + static fromReader(reader: Reader): MessageActionRequestedPeerSentMe; + } export class MessageActionPaymentRefunded extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; currency: string; totalAmount: long; payload?: bytes; charge: Api.TypePaymentCharge; }> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; currency: string; totalAmount: long; payload?: bytes; charge: Api.TypePaymentCharge; - }; + static fromReader(reader: Reader): MessageActionPaymentRefunded; + } export class MessageActionGiftStars extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; currency: string; amount: long; stars: long; @@ -2343,31 +2504,33 @@ namespace Api { cryptoAmount?: long; transactionId?: string; }> { - // flags: undefined; + // flags: Api.Type; currency: string; amount: long; stars: long; cryptoCurrency?: string; cryptoAmount?: long; transactionId?: string; - }; + static fromReader(reader: Reader): MessageActionGiftStars; + } export class MessageActionPrizeStars extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; unclaimed?: true; stars: long; transactionId: string; boostPeer: Api.TypePeer; giveawayMsgId: int; }> { - // flags: undefined; + // flags: Api.Type; unclaimed?: true; stars: long; transactionId: string; boostPeer: Api.TypePeer; giveawayMsgId: int; - }; + static fromReader(reader: Reader): MessageActionPrizeStars; + } export class MessageActionStarGift extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; nameHidden?: true; saved?: true; converted?: true; @@ -2380,7 +2543,7 @@ namespace Api { upgradeMsgId?: int; upgradeStars?: long; }> { - // flags: undefined; + // flags: Api.Type; nameHidden?: true; saved?: true; converted?: true; @@ -2392,9 +2555,10 @@ namespace Api { convertStars?: long; upgradeMsgId?: int; upgradeStars?: long; - }; + static fromReader(reader: Reader): MessageActionStarGift; + } export class MessageActionStarGiftUnique extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; upgrade?: true; transferred?: true; saved?: true; @@ -2403,7 +2567,7 @@ namespace Api { canExportAt?: int; transferStars?: long; }> { - // flags: undefined; + // flags: Api.Type; upgrade?: true; transferred?: true; saved?: true; @@ -2411,9 +2575,10 @@ namespace Api { gift: Api.TypeStarGift; canExportAt?: int; transferStars?: long; - }; + static fromReader(reader: Reader): MessageActionStarGiftUnique; + } export class Dialog extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; pinned?: true; unreadMark?: true; viewForumAsMessages?: true; @@ -2430,7 +2595,7 @@ namespace Api { folderId?: int; ttlPeriod?: int; }> { - // flags: undefined; + // flags: Api.Type; pinned?: true; unreadMark?: true; viewForumAsMessages?: true; @@ -2446,9 +2611,10 @@ namespace Api { draft?: Api.TypeDraftMessage; folderId?: int; ttlPeriod?: int; - }; + static fromReader(reader: Reader): Dialog; + } export class DialogFolder extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; pinned?: true; folder: Api.TypeFolder; peer: Api.TypePeer; @@ -2458,7 +2624,7 @@ namespace Api { unreadMutedMessagesCount: int; unreadUnmutedMessagesCount: int; }> { - // flags: undefined; + // flags: Api.Type; pinned?: true; folder: Api.TypeFolder; peer: Api.TypePeer; @@ -2467,14 +2633,16 @@ namespace Api { unreadUnmutedPeersCount: int; unreadMutedMessagesCount: int; unreadUnmutedMessagesCount: int; - }; + static fromReader(reader: Reader): DialogFolder; + } export class PhotoEmpty extends VirtualClass<{ id: long; }> { id: long; - }; + static fromReader(reader: Reader): PhotoEmpty; + } export class Photo extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; hasStickers?: true; id: long; accessHash: long; @@ -2484,7 +2652,7 @@ namespace Api { videoSizes?: Api.TypeVideoSize[]; dcId: int; }> { - // flags: undefined; + // flags: Api.Type; hasStickers?: true; id: long; accessHash: long; @@ -2493,12 +2661,14 @@ namespace Api { sizes: Api.TypePhotoSize[]; videoSizes?: Api.TypeVideoSize[]; dcId: int; - }; + static fromReader(reader: Reader): Photo; + } export class PhotoSizeEmpty extends VirtualClass<{ type: string; }> { type: string; - }; + static fromReader(reader: Reader): PhotoSizeEmpty; + } export class PhotoSize extends VirtualClass<{ type: string; w: int; @@ -2509,7 +2679,8 @@ namespace Api { w: int; h: int; size: int; - }; + static fromReader(reader: Reader): PhotoSize; + } export class PhotoCachedSize extends VirtualClass<{ type: string; w: int; @@ -2520,14 +2691,16 @@ namespace Api { w: int; h: int; bytes: bytes; - }; + static fromReader(reader: Reader): PhotoCachedSize; + } export class PhotoStrippedSize extends VirtualClass<{ type: string; bytes: bytes; }> { type: string; bytes: bytes; - }; + static fromReader(reader: Reader): PhotoStrippedSize; + } export class PhotoSizeProgressive extends VirtualClass<{ type: string; w: int; @@ -2538,45 +2711,58 @@ namespace Api { w: int; h: int; sizes: int[]; - }; + static fromReader(reader: Reader): PhotoSizeProgressive; + } export class PhotoPathSize extends VirtualClass<{ type: string; bytes: bytes; }> { type: string; bytes: bytes; - }; - export class GeoPointEmpty extends VirtualClass {}; + static fromReader(reader: Reader): PhotoPathSize; + } + export class GeoPointEmpty extends VirtualClass { + static fromReader(reader: Reader): GeoPointEmpty; + } export class GeoPoint extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; long: double; lat: double; accessHash: long; accuracyRadius?: int; }> { - // flags: undefined; + // flags: Api.Type; long: double; lat: double; accessHash: long; accuracyRadius?: int; - }; + static fromReader(reader: Reader): GeoPoint; + } export class InputNotifyPeer extends VirtualClass<{ peer: Api.TypeInputPeer; }> { peer: Api.TypeInputPeer; - }; - export class InputNotifyUsers extends VirtualClass {}; - export class InputNotifyChats extends VirtualClass {}; - export class InputNotifyBroadcasts extends VirtualClass {}; + static fromReader(reader: Reader): InputNotifyPeer; + } + export class InputNotifyUsers extends VirtualClass { + static fromReader(reader: Reader): InputNotifyUsers; + } + export class InputNotifyChats extends VirtualClass { + static fromReader(reader: Reader): InputNotifyChats; + } + export class InputNotifyBroadcasts extends VirtualClass { + static fromReader(reader: Reader): InputNotifyBroadcasts; + } export class InputNotifyForumTopic extends VirtualClass<{ peer: Api.TypeInputPeer; topMsgId: int; }> { peer: Api.TypeInputPeer; topMsgId: int; - }; + static fromReader(reader: Reader): InputNotifyForumTopic; + } export class InputPeerNotifySettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; showPreviews?: Bool; silent?: Bool; muteUntil?: int; @@ -2585,7 +2771,7 @@ namespace Api { storiesHideSender?: Bool; storiesSound?: Api.TypeNotificationSound; } | void> { - // flags: undefined; + // flags: Api.Type; showPreviews?: Bool; silent?: Bool; muteUntil?: int; @@ -2593,9 +2779,10 @@ namespace Api { storiesMuted?: Bool; storiesHideSender?: Bool; storiesSound?: Api.TypeNotificationSound; - }; + static fromReader(reader: Reader): InputPeerNotifySettings; + } export class PeerNotifySettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; showPreviews?: Bool; silent?: Bool; muteUntil?: int; @@ -2608,7 +2795,7 @@ namespace Api { storiesAndroidSound?: Api.TypeNotificationSound; storiesOtherSound?: Api.TypeNotificationSound; } | void> { - // flags: undefined; + // flags: Api.Type; showPreviews?: Bool; silent?: Bool; muteUntil?: int; @@ -2620,9 +2807,10 @@ namespace Api { storiesIosSound?: Api.TypeNotificationSound; storiesAndroidSound?: Api.TypeNotificationSound; storiesOtherSound?: Api.TypeNotificationSound; - }; + static fromReader(reader: Reader): PeerNotifySettings; + } export class PeerSettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; reportSpam?: true; addContact?: true; blockContact?: true; @@ -2640,7 +2828,7 @@ namespace Api { businessBotId?: long; businessBotManageUrl?: string; } | void> { - // flags: undefined; + // flags: Api.Type; reportSpam?: true; addContact?: true; blockContact?: true; @@ -2657,10 +2845,11 @@ namespace Api { requestChatDate?: int; businessBotId?: long; businessBotManageUrl?: string; - }; + static fromReader(reader: Reader): PeerSettings; + } export class WallPaper extends VirtualClass<{ id: long; - // flags: undefined; + // flags: Api.Type; creator?: true; default?: true; pattern?: true; @@ -2671,7 +2860,7 @@ namespace Api { settings?: Api.TypeWallPaperSettings; }> { id: long; - // flags: undefined; + // flags: Api.Type; creator?: true; default?: true; pattern?: true; @@ -2680,32 +2869,54 @@ namespace Api { slug: string; document: Api.TypeDocument; settings?: Api.TypeWallPaperSettings; - }; + static fromReader(reader: Reader): WallPaper; + } export class WallPaperNoFile extends VirtualClass<{ id: long; - // flags: undefined; + // flags: Api.Type; default?: true; dark?: true; settings?: Api.TypeWallPaperSettings; }> { id: long; - // flags: undefined; + // flags: Api.Type; default?: true; dark?: true; settings?: Api.TypeWallPaperSettings; - }; - export class InputReportReasonSpam extends VirtualClass {}; - export class InputReportReasonViolence extends VirtualClass {}; - export class InputReportReasonPornography extends VirtualClass {}; - export class InputReportReasonChildAbuse extends VirtualClass {}; - export class InputReportReasonOther extends VirtualClass {}; - export class InputReportReasonCopyright extends VirtualClass {}; - export class InputReportReasonGeoIrrelevant extends VirtualClass {}; - export class InputReportReasonFake extends VirtualClass {}; - export class InputReportReasonIllegalDrugs extends VirtualClass {}; - export class InputReportReasonPersonalDetails extends VirtualClass {}; + static fromReader(reader: Reader): WallPaperNoFile; + } + export class InputReportReasonSpam extends VirtualClass { + static fromReader(reader: Reader): InputReportReasonSpam; + } + export class InputReportReasonViolence extends VirtualClass { + static fromReader(reader: Reader): InputReportReasonViolence; + } + export class InputReportReasonPornography extends VirtualClass { + static fromReader(reader: Reader): InputReportReasonPornography; + } + export class InputReportReasonChildAbuse extends VirtualClass { + static fromReader(reader: Reader): InputReportReasonChildAbuse; + } + export class InputReportReasonOther extends VirtualClass { + static fromReader(reader: Reader): InputReportReasonOther; + } + export class InputReportReasonCopyright extends VirtualClass { + static fromReader(reader: Reader): InputReportReasonCopyright; + } + export class InputReportReasonGeoIrrelevant extends VirtualClass { + static fromReader(reader: Reader): InputReportReasonGeoIrrelevant; + } + export class InputReportReasonFake extends VirtualClass { + static fromReader(reader: Reader): InputReportReasonFake; + } + export class InputReportReasonIllegalDrugs extends VirtualClass { + static fromReader(reader: Reader): InputReportReasonIllegalDrugs; + } + export class InputReportReasonPersonalDetails extends VirtualClass { + static fromReader(reader: Reader): InputReportReasonPersonalDetails; + } export class UserFull extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; blocked?: true; phoneCallsAvailable?: true; phoneCallsPrivate?: true; @@ -2719,7 +2930,7 @@ namespace Api { wallpaperOverridden?: true; contactRequirePremium?: true; readDatesPrivate?: true; - // flags2: undefined; + // flags2: Api.Type; sponsoredEnabled?: true; canViewRevenue?: true; botCanManageEmojiStatus?: true; @@ -2754,7 +2965,7 @@ namespace Api { starrefProgram?: Api.TypeStarRefProgram; botVerification?: Api.TypeBotVerification; }> { - // flags: undefined; + // flags: Api.Type; blocked?: true; phoneCallsAvailable?: true; phoneCallsPrivate?: true; @@ -2768,7 +2979,7 @@ namespace Api { wallpaperOverridden?: true; contactRequirePremium?: true; readDatesPrivate?: true; - // flags2: undefined; + // flags2: Api.Type; sponsoredEnabled?: true; canViewRevenue?: true; botCanManageEmojiStatus?: true; @@ -2802,51 +3013,88 @@ namespace Api { stargiftsCount?: int; starrefProgram?: Api.TypeStarRefProgram; botVerification?: Api.TypeBotVerification; - }; + static fromReader(reader: Reader): UserFull; + } export class Contact extends VirtualClass<{ userId: long; mutual: Bool; }> { userId: long; mutual: Bool; - }; + static fromReader(reader: Reader): Contact; + } export class ImportedContact extends VirtualClass<{ userId: long; clientId: long; }> { userId: long; clientId: long; - }; + static fromReader(reader: Reader): ImportedContact; + } export class ContactStatus extends VirtualClass<{ userId: long; status: Api.TypeUserStatus; }> { userId: long; status: Api.TypeUserStatus; - }; - export class InputMessagesFilterEmpty extends VirtualClass {}; - export class InputMessagesFilterPhotos extends VirtualClass {}; - export class InputMessagesFilterVideo extends VirtualClass {}; - export class InputMessagesFilterPhotoVideo extends VirtualClass {}; - export class InputMessagesFilterDocument extends VirtualClass {}; - export class InputMessagesFilterUrl extends VirtualClass {}; - export class InputMessagesFilterGif extends VirtualClass {}; - export class InputMessagesFilterVoice extends VirtualClass {}; - export class InputMessagesFilterMusic extends VirtualClass {}; - export class InputMessagesFilterChatPhotos extends VirtualClass {}; + static fromReader(reader: Reader): ContactStatus; + } + export class InputMessagesFilterEmpty extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterEmpty; + } + export class InputMessagesFilterPhotos extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterPhotos; + } + export class InputMessagesFilterVideo extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterVideo; + } + export class InputMessagesFilterPhotoVideo extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterPhotoVideo; + } + export class InputMessagesFilterDocument extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterDocument; + } + export class InputMessagesFilterUrl extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterUrl; + } + export class InputMessagesFilterGif extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterGif; + } + export class InputMessagesFilterVoice extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterVoice; + } + export class InputMessagesFilterMusic extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterMusic; + } + export class InputMessagesFilterChatPhotos extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterChatPhotos; + } export class InputMessagesFilterPhoneCalls extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; missed?: true; } | void> { - // flags: undefined; + // flags: Api.Type; missed?: true; - }; - export class InputMessagesFilterRoundVoice extends VirtualClass {}; - export class InputMessagesFilterRoundVideo extends VirtualClass {}; - export class InputMessagesFilterMyMentions extends VirtualClass {}; - export class InputMessagesFilterGeo extends VirtualClass {}; - export class InputMessagesFilterContacts extends VirtualClass {}; - export class InputMessagesFilterPinned extends VirtualClass {}; + static fromReader(reader: Reader): InputMessagesFilterPhoneCalls; + } + export class InputMessagesFilterRoundVoice extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterRoundVoice; + } + export class InputMessagesFilterRoundVideo extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterRoundVideo; + } + export class InputMessagesFilterMyMentions extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterMyMentions; + } + export class InputMessagesFilterGeo extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterGeo; + } + export class InputMessagesFilterContacts extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterContacts; + } + export class InputMessagesFilterPinned extends VirtualClass { + static fromReader(reader: Reader): InputMessagesFilterPinned; + } export class UpdateNewMessage extends VirtualClass<{ message: Api.TypeMessage; pts: int; @@ -2855,14 +3103,16 @@ namespace Api { message: Api.TypeMessage; pts: int; ptsCount: int; - }; + static fromReader(reader: Reader): UpdateNewMessage; + } export class UpdateMessageID extends VirtualClass<{ id: int; randomId: long; }> { id: int; randomId: long; - }; + static fromReader(reader: Reader): UpdateMessageID; + } export class UpdateDeleteMessages extends VirtualClass<{ messages: int[]; pts: int; @@ -2871,14 +3121,16 @@ namespace Api { messages: int[]; pts: int; ptsCount: int; - }; + static fromReader(reader: Reader): UpdateDeleteMessages; + } export class UpdateUserTyping extends VirtualClass<{ userId: long; action: Api.TypeSendMessageAction; }> { userId: long; action: Api.TypeSendMessageAction; - }; + static fromReader(reader: Reader): UpdateUserTyping; + } export class UpdateChatUserTyping extends VirtualClass<{ chatId: long; fromId: Api.TypePeer; @@ -2887,19 +3139,22 @@ namespace Api { chatId: long; fromId: Api.TypePeer; action: Api.TypeSendMessageAction; - }; + static fromReader(reader: Reader): UpdateChatUserTyping; + } export class UpdateChatParticipants extends VirtualClass<{ participants: Api.TypeChatParticipants; }> { participants: Api.TypeChatParticipants; - }; + static fromReader(reader: Reader): UpdateChatParticipants; + } export class UpdateUserStatus extends VirtualClass<{ userId: long; status: Api.TypeUserStatus; }> { userId: long; status: Api.TypeUserStatus; - }; + static fromReader(reader: Reader): UpdateUserStatus; + } export class UpdateUserName extends VirtualClass<{ userId: long; firstName: string; @@ -2910,41 +3165,46 @@ namespace Api { firstName: string; lastName: string; usernames: Api.TypeUsername[]; - }; + static fromReader(reader: Reader): UpdateUserName; + } export class UpdateNewAuthorization extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; unconfirmed?: true; hash: long; date?: int; device?: string; location?: string; }> { - // flags: undefined; + // flags: Api.Type; unconfirmed?: true; hash: long; date?: int; device?: string; location?: string; - }; + static fromReader(reader: Reader): UpdateNewAuthorization; + } export class UpdateNewEncryptedMessage extends VirtualClass<{ message: Api.TypeEncryptedMessage; qts: int; }> { message: Api.TypeEncryptedMessage; qts: int; - }; + static fromReader(reader: Reader): UpdateNewEncryptedMessage; + } export class UpdateEncryptedChatTyping extends VirtualClass<{ chatId: int; }> { chatId: int; - }; + static fromReader(reader: Reader): UpdateEncryptedChatTyping; + } export class UpdateEncryption extends VirtualClass<{ chat: Api.TypeEncryptedChat; date: int; }> { chat: Api.TypeEncryptedChat; date: int; - }; + static fromReader(reader: Reader): UpdateEncryption; + } export class UpdateEncryptedMessagesRead extends VirtualClass<{ chatId: int; maxDate: int; @@ -2953,7 +3213,8 @@ namespace Api { chatId: int; maxDate: int; date: int; - }; + static fromReader(reader: Reader): UpdateEncryptedMessagesRead; + } export class UpdateChatParticipantAdd extends VirtualClass<{ chatId: long; userId: long; @@ -2966,7 +3227,8 @@ namespace Api { inviterId: long; date: int; version: int; - }; + static fromReader(reader: Reader): UpdateChatParticipantAdd; + } export class UpdateChatParticipantDelete extends VirtualClass<{ chatId: long; userId: long; @@ -2975,21 +3237,24 @@ namespace Api { chatId: long; userId: long; version: int; - }; + static fromReader(reader: Reader): UpdateChatParticipantDelete; + } export class UpdateDcOptions extends VirtualClass<{ dcOptions: Api.TypeDcOption[]; }> { dcOptions: Api.TypeDcOption[]; - }; + static fromReader(reader: Reader): UpdateDcOptions; + } export class UpdateNotifySettings extends VirtualClass<{ peer: Api.TypeNotifyPeer; notifySettings: Api.TypePeerNotifySettings; }> { peer: Api.TypeNotifyPeer; notifySettings: Api.TypePeerNotifySettings; - }; + static fromReader(reader: Reader): UpdateNotifySettings; + } export class UpdateServiceNotification extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; popup?: true; invertMedia?: true; inboxDate?: int; @@ -2998,7 +3263,7 @@ namespace Api { media: Api.TypeMessageMedia; entities: Api.TypeMessageEntity[]; }> { - // flags: undefined; + // flags: Api.Type; popup?: true; invertMedia?: true; inboxDate?: int; @@ -3006,23 +3271,26 @@ namespace Api { message: string; media: Api.TypeMessageMedia; entities: Api.TypeMessageEntity[]; - }; + static fromReader(reader: Reader): UpdateServiceNotification; + } export class UpdatePrivacy extends VirtualClass<{ key: Api.TypePrivacyKey; rules: Api.TypePrivacyRule[]; }> { key: Api.TypePrivacyKey; rules: Api.TypePrivacyRule[]; - }; + static fromReader(reader: Reader): UpdatePrivacy; + } export class UpdateUserPhone extends VirtualClass<{ userId: long; phone: string; }> { userId: long; phone: string; - }; + static fromReader(reader: Reader): UpdateUserPhone; + } export class UpdateReadHistoryInbox extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; folderId?: int; peer: Api.TypePeer; maxId: int; @@ -3030,14 +3298,15 @@ namespace Api { pts: int; ptsCount: int; }> { - // flags: undefined; + // flags: Api.Type; folderId?: int; peer: Api.TypePeer; maxId: int; stillUnreadCount: int; pts: int; ptsCount: int; - }; + static fromReader(reader: Reader): UpdateReadHistoryInbox; + } export class UpdateReadHistoryOutbox extends VirtualClass<{ peer: Api.TypePeer; maxId: int; @@ -3048,7 +3317,8 @@ namespace Api { maxId: int; pts: int; ptsCount: int; - }; + static fromReader(reader: Reader): UpdateReadHistoryOutbox; + } export class UpdateWebPage extends VirtualClass<{ webpage: Api.TypeWebPage; pts: int; @@ -3057,34 +3327,38 @@ namespace Api { webpage: Api.TypeWebPage; pts: int; ptsCount: int; - }; + static fromReader(reader: Reader): UpdateWebPage; + } export class UpdateReadMessagesContents extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; messages: int[]; pts: int; ptsCount: int; date?: int; }> { - // flags: undefined; + // flags: Api.Type; messages: int[]; pts: int; ptsCount: int; date?: int; - }; + static fromReader(reader: Reader): UpdateReadMessagesContents; + } export class UpdateChannelTooLong extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; channelId: long; pts?: int; }> { - // flags: undefined; + // flags: Api.Type; channelId: long; pts?: int; - }; + static fromReader(reader: Reader): UpdateChannelTooLong; + } export class UpdateChannel extends VirtualClass<{ channelId: long; }> { channelId: long; - }; + static fromReader(reader: Reader): UpdateChannel; + } export class UpdateNewChannelMessage extends VirtualClass<{ message: Api.TypeMessage; pts: int; @@ -3093,22 +3367,24 @@ namespace Api { message: Api.TypeMessage; pts: int; ptsCount: int; - }; + static fromReader(reader: Reader): UpdateNewChannelMessage; + } export class UpdateReadChannelInbox extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; folderId?: int; channelId: long; maxId: int; stillUnreadCount: int; pts: int; }> { - // flags: undefined; + // flags: Api.Type; folderId?: int; channelId: long; maxId: int; stillUnreadCount: int; pts: int; - }; + static fromReader(reader: Reader): UpdateReadChannelInbox; + } export class UpdateDeleteChannelMessages extends VirtualClass<{ channelId: long; messages: int[]; @@ -3119,7 +3395,8 @@ namespace Api { messages: int[]; pts: int; ptsCount: int; - }; + static fromReader(reader: Reader): UpdateDeleteChannelMessages; + } export class UpdateChannelMessageViews extends VirtualClass<{ channelId: long; id: int; @@ -3128,7 +3405,8 @@ namespace Api { channelId: long; id: int; views: int; - }; + static fromReader(reader: Reader): UpdateChannelMessageViews; + } export class UpdateChatParticipantAdmin extends VirtualClass<{ chatId: long; userId: long; @@ -3139,35 +3417,41 @@ namespace Api { userId: long; isAdmin: Bool; version: int; - }; + static fromReader(reader: Reader): UpdateChatParticipantAdmin; + } export class UpdateNewStickerSet extends VirtualClass<{ stickerset: messages.TypeStickerSet; }> { stickerset: messages.TypeStickerSet; - }; + static fromReader(reader: Reader): UpdateNewStickerSet; + } export class UpdateStickerSetsOrder extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; masks?: true; emojis?: true; order: long[]; }> { - // flags: undefined; + // flags: Api.Type; masks?: true; emojis?: true; order: long[]; - }; + static fromReader(reader: Reader): UpdateStickerSetsOrder; + } export class UpdateStickerSets extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; masks?: true; emojis?: true; } | void> { - // flags: undefined; + // flags: Api.Type; masks?: true; emojis?: true; - }; - export class UpdateSavedGifs extends VirtualClass {}; + static fromReader(reader: Reader): UpdateStickerSets; + } + export class UpdateSavedGifs extends VirtualClass { + static fromReader(reader: Reader): UpdateSavedGifs; + } export class UpdateBotInlineQuery extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; queryId: long; userId: long; query: string; @@ -3175,29 +3459,31 @@ namespace Api { peerType?: Api.TypeInlineQueryPeerType; offset: string; }> { - // flags: undefined; + // flags: Api.Type; queryId: long; userId: long; query: string; geo?: Api.TypeGeoPoint; peerType?: Api.TypeInlineQueryPeerType; offset: string; - }; + static fromReader(reader: Reader): UpdateBotInlineQuery; + } export class UpdateBotInlineSend extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; userId: long; query: string; geo?: Api.TypeGeoPoint; id: string; msgId?: Api.TypeInputBotInlineMessageID; }> { - // flags: undefined; + // flags: Api.Type; userId: long; query: string; geo?: Api.TypeGeoPoint; id: string; msgId?: Api.TypeInputBotInlineMessageID; - }; + static fromReader(reader: Reader): UpdateBotInlineSend; + } export class UpdateEditChannelMessage extends VirtualClass<{ message: Api.TypeMessage; pts: int; @@ -3206,9 +3492,10 @@ namespace Api { message: Api.TypeMessage; pts: int; ptsCount: int; - }; + static fromReader(reader: Reader): UpdateEditChannelMessage; + } export class UpdateBotCallbackQuery extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; queryId: long; userId: long; peer: Api.TypePeer; @@ -3217,7 +3504,7 @@ namespace Api { data?: bytes; gameShortName?: string; }> { - // flags: undefined; + // flags: Api.Type; queryId: long; userId: long; peer: Api.TypePeer; @@ -3225,7 +3512,8 @@ namespace Api { chatInstance: long; data?: bytes; gameShortName?: string; - }; + static fromReader(reader: Reader): UpdateBotCallbackQuery; + } export class UpdateEditMessage extends VirtualClass<{ message: Api.TypeMessage; pts: int; @@ -3234,9 +3522,10 @@ namespace Api { message: Api.TypeMessage; pts: int; ptsCount: int; - }; + static fromReader(reader: Reader): UpdateEditMessage; + } export class UpdateInlineBotCallbackQuery extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; queryId: long; userId: long; msgId: Api.TypeInputBotInlineMessageID; @@ -3244,36 +3533,47 @@ namespace Api { data?: bytes; gameShortName?: string; }> { - // flags: undefined; + // flags: Api.Type; queryId: long; userId: long; msgId: Api.TypeInputBotInlineMessageID; chatInstance: long; data?: bytes; gameShortName?: string; - }; + static fromReader(reader: Reader): UpdateInlineBotCallbackQuery; + } export class UpdateReadChannelOutbox extends VirtualClass<{ channelId: long; maxId: int; }> { channelId: long; maxId: int; - }; + static fromReader(reader: Reader): UpdateReadChannelOutbox; + } export class UpdateDraftMessage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; topMsgId?: int; draft: Api.TypeDraftMessage; }> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; topMsgId?: int; draft: Api.TypeDraftMessage; - }; - export class UpdateReadFeaturedStickers extends VirtualClass {}; - export class UpdateRecentStickers extends VirtualClass {}; - export class UpdateConfig extends VirtualClass {}; - export class UpdatePtsChanged extends VirtualClass {}; + static fromReader(reader: Reader): UpdateDraftMessage; + } + export class UpdateReadFeaturedStickers extends VirtualClass { + static fromReader(reader: Reader): UpdateReadFeaturedStickers; + } + export class UpdateRecentStickers extends VirtualClass { + static fromReader(reader: Reader): UpdateRecentStickers; + } + export class UpdateConfig extends VirtualClass { + static fromReader(reader: Reader): UpdateConfig; + } + export class UpdatePtsChanged extends VirtualClass { + static fromReader(reader: Reader): UpdatePtsChanged; + } export class UpdateChannelWebPage extends VirtualClass<{ channelId: long; webpage: Api.TypeWebPage; @@ -3284,32 +3584,36 @@ namespace Api { webpage: Api.TypeWebPage; pts: int; ptsCount: int; - }; + static fromReader(reader: Reader): UpdateChannelWebPage; + } export class UpdateDialogPinned extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; pinned?: true; folderId?: int; peer: Api.TypeDialogPeer; }> { - // flags: undefined; + // flags: Api.Type; pinned?: true; folderId?: int; peer: Api.TypeDialogPeer; - }; + static fromReader(reader: Reader): UpdateDialogPinned; + } export class UpdatePinnedDialogs extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; folderId?: int; order?: Api.TypeDialogPeer[]; } | void> { - // flags: undefined; + // flags: Api.Type; folderId?: int; order?: Api.TypeDialogPeer[]; - }; + static fromReader(reader: Reader): UpdatePinnedDialogs; + } export class UpdateBotWebhookJSON extends VirtualClass<{ data: Api.TypeDataJSON; }> { data: Api.TypeDataJSON; - }; + static fromReader(reader: Reader): UpdateBotWebhookJSON; + } export class UpdateBotWebhookJSONQuery extends VirtualClass<{ queryId: long; data: Api.TypeDataJSON; @@ -3318,7 +3622,8 @@ namespace Api { queryId: long; data: Api.TypeDataJSON; timeout: int; - }; + static fromReader(reader: Reader): UpdateBotWebhookJSONQuery; + } export class UpdateBotShippingQuery extends VirtualClass<{ queryId: long; userId: long; @@ -3329,9 +3634,10 @@ namespace Api { userId: long; payload: bytes; shippingAddress: Api.TypePostAddress; - }; + static fromReader(reader: Reader): UpdateBotShippingQuery; + } export class UpdateBotPrecheckoutQuery extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; queryId: long; userId: long; payload: bytes; @@ -3340,7 +3646,7 @@ namespace Api { currency: string; totalAmount: long; }> { - // flags: undefined; + // flags: Api.Type; queryId: long; userId: long; payload: bytes; @@ -3348,62 +3654,74 @@ namespace Api { shippingOptionId?: string; currency: string; totalAmount: long; - }; + static fromReader(reader: Reader): UpdateBotPrecheckoutQuery; + } export class UpdatePhoneCall extends VirtualClass<{ phoneCall: Api.TypePhoneCall; }> { phoneCall: Api.TypePhoneCall; - }; + static fromReader(reader: Reader): UpdatePhoneCall; + } export class UpdateLangPackTooLong extends VirtualClass<{ langCode: string; }> { langCode: string; - }; + static fromReader(reader: Reader): UpdateLangPackTooLong; + } export class UpdateLangPack extends VirtualClass<{ difference: Api.TypeLangPackDifference; }> { difference: Api.TypeLangPackDifference; - }; - export class UpdateFavedStickers extends VirtualClass {}; + static fromReader(reader: Reader): UpdateLangPack; + } + export class UpdateFavedStickers extends VirtualClass { + static fromReader(reader: Reader): UpdateFavedStickers; + } export class UpdateChannelReadMessagesContents extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; channelId: long; topMsgId?: int; messages: int[]; }> { - // flags: undefined; + // flags: Api.Type; channelId: long; topMsgId?: int; messages: int[]; - }; - export class UpdateContactsReset extends VirtualClass {}; + static fromReader(reader: Reader): UpdateChannelReadMessagesContents; + } + export class UpdateContactsReset extends VirtualClass { + static fromReader(reader: Reader): UpdateContactsReset; + } export class UpdateChannelAvailableMessages extends VirtualClass<{ channelId: long; availableMinId: int; }> { channelId: long; availableMinId: int; - }; + static fromReader(reader: Reader): UpdateChannelAvailableMessages; + } export class UpdateDialogUnreadMark extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; unread?: true; peer: Api.TypeDialogPeer; }> { - // flags: undefined; + // flags: Api.Type; unread?: true; peer: Api.TypeDialogPeer; - }; + static fromReader(reader: Reader): UpdateDialogUnreadMark; + } export class UpdateMessagePoll extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; pollId: long; poll?: Api.TypePoll; results: Api.TypePollResults; }> { - // flags: undefined; + // flags: Api.Type; pollId: long; poll?: Api.TypePoll; results: Api.TypePollResults; - }; + static fromReader(reader: Reader): UpdateMessagePoll; + } export class UpdateChatDefaultBannedRights extends VirtualClass<{ peer: Api.TypePeer; defaultBannedRights: Api.TypeChatBannedRights; @@ -3412,7 +3730,8 @@ namespace Api { peer: Api.TypePeer; defaultBannedRights: Api.TypeChatBannedRights; version: int; - }; + static fromReader(reader: Reader): UpdateChatDefaultBannedRights; + } export class UpdateFolderPeers extends VirtualClass<{ folderPeers: Api.TypeFolderPeer[]; pts: int; @@ -3421,48 +3740,57 @@ namespace Api { folderPeers: Api.TypeFolderPeer[]; pts: int; ptsCount: int; - }; + static fromReader(reader: Reader): UpdateFolderPeers; + } export class UpdatePeerSettings extends VirtualClass<{ peer: Api.TypePeer; settings: Api.TypePeerSettings; }> { peer: Api.TypePeer; settings: Api.TypePeerSettings; - }; + static fromReader(reader: Reader): UpdatePeerSettings; + } export class UpdatePeerLocated extends VirtualClass<{ peers: Api.TypePeerLocated[]; }> { peers: Api.TypePeerLocated[]; - }; + static fromReader(reader: Reader): UpdatePeerLocated; + } export class UpdateNewScheduledMessage extends VirtualClass<{ message: Api.TypeMessage; }> { message: Api.TypeMessage; - }; + static fromReader(reader: Reader): UpdateNewScheduledMessage; + } export class UpdateDeleteScheduledMessages extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; messages: int[]; sentMessages?: int[]; }> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; messages: int[]; sentMessages?: int[]; - }; + static fromReader(reader: Reader): UpdateDeleteScheduledMessages; + } export class UpdateTheme extends VirtualClass<{ theme: Api.TypeTheme; }> { theme: Api.TypeTheme; - }; + static fromReader(reader: Reader): UpdateTheme; + } export class UpdateGeoLiveViewed extends VirtualClass<{ peer: Api.TypePeer; msgId: int; }> { peer: Api.TypePeer; msgId: int; - }; - export class UpdateLoginToken extends VirtualClass {}; + static fromReader(reader: Reader): UpdateGeoLiveViewed; + } + export class UpdateLoginToken extends VirtualClass { + static fromReader(reader: Reader): UpdateLoginToken; + } export class UpdateMessagePollVote extends VirtualClass<{ pollId: long; peer: Api.TypePeer; @@ -3473,29 +3801,35 @@ namespace Api { peer: Api.TypePeer; options: bytes[]; qts: int; - }; + static fromReader(reader: Reader): UpdateMessagePollVote; + } export class UpdateDialogFilter extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; id: int; filter?: Api.TypeDialogFilter; }> { - // flags: undefined; + // flags: Api.Type; id: int; filter?: Api.TypeDialogFilter; - }; + static fromReader(reader: Reader): UpdateDialogFilter; + } export class UpdateDialogFilterOrder extends VirtualClass<{ order: int[]; }> { order: int[]; - }; - export class UpdateDialogFilters extends VirtualClass {}; + static fromReader(reader: Reader): UpdateDialogFilterOrder; + } + export class UpdateDialogFilters extends VirtualClass { + static fromReader(reader: Reader): UpdateDialogFilters; + } export class UpdatePhoneCallSignalingData extends VirtualClass<{ phoneCallId: long; data: bytes; }> { phoneCallId: long; data: bytes; - }; + static fromReader(reader: Reader): UpdatePhoneCallSignalingData; + } export class UpdateChannelMessageForwards extends VirtualClass<{ channelId: long; id: int; @@ -3504,22 +3838,24 @@ namespace Api { channelId: long; id: int; forwards: int; - }; + static fromReader(reader: Reader): UpdateChannelMessageForwards; + } export class UpdateReadChannelDiscussionInbox extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; channelId: long; topMsgId: int; readMaxId: int; broadcastId?: long; broadcastPost?: int; }> { - // flags: undefined; + // flags: Api.Type; channelId: long; topMsgId: int; readMaxId: int; broadcastId?: long; broadcastPost?: int; - }; + static fromReader(reader: Reader): UpdateReadChannelDiscussionInbox; + } export class UpdateReadChannelDiscussionOutbox extends VirtualClass<{ channelId: long; topMsgId: int; @@ -3528,66 +3864,72 @@ namespace Api { channelId: long; topMsgId: int; readMaxId: int; - }; + static fromReader(reader: Reader): UpdateReadChannelDiscussionOutbox; + } export class UpdatePeerBlocked extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; blocked?: true; blockedMyStoriesFrom?: true; peerId: Api.TypePeer; }> { - // flags: undefined; + // flags: Api.Type; blocked?: true; blockedMyStoriesFrom?: true; peerId: Api.TypePeer; - }; + static fromReader(reader: Reader): UpdatePeerBlocked; + } export class UpdateChannelUserTyping extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; channelId: long; topMsgId?: int; fromId: Api.TypePeer; action: Api.TypeSendMessageAction; }> { - // flags: undefined; + // flags: Api.Type; channelId: long; topMsgId?: int; fromId: Api.TypePeer; action: Api.TypeSendMessageAction; - }; + static fromReader(reader: Reader): UpdateChannelUserTyping; + } export class UpdatePinnedMessages extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; pinned?: true; peer: Api.TypePeer; messages: int[]; pts: int; ptsCount: int; }> { - // flags: undefined; + // flags: Api.Type; pinned?: true; peer: Api.TypePeer; messages: int[]; pts: int; ptsCount: int; - }; + static fromReader(reader: Reader): UpdatePinnedMessages; + } export class UpdatePinnedChannelMessages extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; pinned?: true; channelId: long; messages: int[]; pts: int; ptsCount: int; }> { - // flags: undefined; + // flags: Api.Type; pinned?: true; channelId: long; messages: int[]; pts: int; ptsCount: int; - }; + static fromReader(reader: Reader): UpdatePinnedChannelMessages; + } export class UpdateChat extends VirtualClass<{ chatId: long; }> { chatId: long; - }; + static fromReader(reader: Reader): UpdateChat; + } export class UpdateGroupCallParticipants extends VirtualClass<{ call: Api.TypeInputGroupCall; participants: Api.TypeGroupCallParticipant[]; @@ -3596,27 +3938,30 @@ namespace Api { call: Api.TypeInputGroupCall; participants: Api.TypeGroupCallParticipant[]; version: int; - }; + static fromReader(reader: Reader): UpdateGroupCallParticipants; + } export class UpdateGroupCall extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; chatId?: long; call: Api.TypeGroupCall; }> { - // flags: undefined; + // flags: Api.Type; chatId?: long; call: Api.TypeGroupCall; - }; + static fromReader(reader: Reader): UpdateGroupCall; + } export class UpdatePeerHistoryTTL extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; ttlPeriod?: int; }> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; ttlPeriod?: int; - }; + static fromReader(reader: Reader): UpdatePeerHistoryTTL; + } export class UpdateChatParticipant extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; chatId: long; date: int; actorId: long; @@ -3626,7 +3971,7 @@ namespace Api { invite?: Api.TypeExportedChatInvite; qts: int; }> { - // flags: undefined; + // flags: Api.Type; chatId: long; date: int; actorId: long; @@ -3635,9 +3980,10 @@ namespace Api { newParticipant?: Api.TypeChatParticipant; invite?: Api.TypeExportedChatInvite; qts: int; - }; + static fromReader(reader: Reader): UpdateChatParticipant; + } export class UpdateChannelParticipant extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; viaChatlist?: true; channelId: long; date: int; @@ -3648,7 +3994,7 @@ namespace Api { invite?: Api.TypeExportedChatInvite; qts: int; }> { - // flags: undefined; + // flags: Api.Type; viaChatlist?: true; channelId: long; date: int; @@ -3658,7 +4004,8 @@ namespace Api { newParticipant?: Api.TypeChannelParticipant; invite?: Api.TypeExportedChatInvite; qts: int; - }; + static fromReader(reader: Reader): UpdateChannelParticipant; + } export class UpdateBotStopped extends VirtualClass<{ userId: long; date: int; @@ -3669,16 +4016,18 @@ namespace Api { date: int; stopped: Bool; qts: int; - }; + static fromReader(reader: Reader): UpdateBotStopped; + } export class UpdateGroupCallConnection extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; presentation?: true; params: Api.TypeDataJSON; }> { - // flags: undefined; + // flags: Api.Type; presentation?: true; params: Api.TypeDataJSON; - }; + static fromReader(reader: Reader): UpdateGroupCallConnection; + } export class UpdateBotCommands extends VirtualClass<{ peer: Api.TypePeer; botId: long; @@ -3687,7 +4036,8 @@ namespace Api { peer: Api.TypePeer; botId: long; commands: Api.TypeBotCommand[]; - }; + static fromReader(reader: Reader): UpdateBotCommands; + } export class UpdatePendingJoinRequests extends VirtualClass<{ peer: Api.TypePeer; requestsPending: int; @@ -3696,7 +4046,8 @@ namespace Api { peer: Api.TypePeer; requestsPending: int; recentRequesters: long[]; - }; + static fromReader(reader: Reader): UpdatePendingJoinRequests; + } export class UpdateBotChatInviteRequester extends VirtualClass<{ peer: Api.TypePeer; date: int; @@ -3711,70 +4062,87 @@ namespace Api { about: string; invite: Api.TypeExportedChatInvite; qts: int; - }; + static fromReader(reader: Reader): UpdateBotChatInviteRequester; + } export class UpdateMessageReactions extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; msgId: int; topMsgId?: int; reactions: Api.TypeMessageReactions; }> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; msgId: int; topMsgId?: int; reactions: Api.TypeMessageReactions; - }; - export class UpdateAttachMenuBots extends VirtualClass {}; + static fromReader(reader: Reader): UpdateMessageReactions; + } + export class UpdateAttachMenuBots extends VirtualClass { + static fromReader(reader: Reader): UpdateAttachMenuBots; + } export class UpdateWebViewResultSent extends VirtualClass<{ queryId: long; }> { queryId: long; - }; + static fromReader(reader: Reader): UpdateWebViewResultSent; + } export class UpdateBotMenuButton extends VirtualClass<{ botId: long; button: Api.TypeBotMenuButton; }> { botId: long; button: Api.TypeBotMenuButton; - }; - export class UpdateSavedRingtones extends VirtualClass {}; + static fromReader(reader: Reader): UpdateBotMenuButton; + } + export class UpdateSavedRingtones extends VirtualClass { + static fromReader(reader: Reader): UpdateSavedRingtones; + } export class UpdateTranscribedAudio extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; pending?: true; peer: Api.TypePeer; msgId: int; transcriptionId: long; text: string; }> { - // flags: undefined; + // flags: Api.Type; pending?: true; peer: Api.TypePeer; msgId: int; transcriptionId: long; text: string; - }; - export class UpdateReadFeaturedEmojiStickers extends VirtualClass {}; + static fromReader(reader: Reader): UpdateTranscribedAudio; + } + export class UpdateReadFeaturedEmojiStickers extends VirtualClass { + static fromReader(reader: Reader): UpdateReadFeaturedEmojiStickers; + } export class UpdateUserEmojiStatus extends VirtualClass<{ userId: long; emojiStatus: Api.TypeEmojiStatus; }> { userId: long; emojiStatus: Api.TypeEmojiStatus; - }; - export class UpdateRecentEmojiStatuses extends VirtualClass {}; - export class UpdateRecentReactions extends VirtualClass {}; + static fromReader(reader: Reader): UpdateUserEmojiStatus; + } + export class UpdateRecentEmojiStatuses extends VirtualClass { + static fromReader(reader: Reader): UpdateRecentEmojiStatuses; + } + export class UpdateRecentReactions extends VirtualClass { + static fromReader(reader: Reader): UpdateRecentReactions; + } export class UpdateMoveStickerSetToTop extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; masks?: true; emojis?: true; stickerset: long; }> { - // flags: undefined; + // flags: Api.Type; masks?: true; emojis?: true; stickerset: long; - }; + static fromReader(reader: Reader): UpdateMoveStickerSetToTop; + } export class UpdateMessageExtendedMedia extends VirtualClass<{ peer: Api.TypePeer; msgId: int; @@ -3783,59 +4151,69 @@ namespace Api { peer: Api.TypePeer; msgId: int; extendedMedia: Api.TypeMessageExtendedMedia[]; - }; + static fromReader(reader: Reader): UpdateMessageExtendedMedia; + } export class UpdateChannelPinnedTopic extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; pinned?: true; channelId: long; topicId: int; }> { - // flags: undefined; + // flags: Api.Type; pinned?: true; channelId: long; topicId: int; - }; + static fromReader(reader: Reader): UpdateChannelPinnedTopic; + } export class UpdateChannelPinnedTopics extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; channelId: long; order?: int[]; }> { - // flags: undefined; + // flags: Api.Type; channelId: long; order?: int[]; - }; + static fromReader(reader: Reader): UpdateChannelPinnedTopics; + } export class UpdateUser extends VirtualClass<{ userId: long; }> { userId: long; - }; - export class UpdateAutoSaveSettings extends VirtualClass {}; + static fromReader(reader: Reader): UpdateUser; + } + export class UpdateAutoSaveSettings extends VirtualClass { + static fromReader(reader: Reader): UpdateAutoSaveSettings; + } export class UpdateStory extends VirtualClass<{ peer: Api.TypePeer; story: Api.TypeStoryItem; }> { peer: Api.TypePeer; story: Api.TypeStoryItem; - }; + static fromReader(reader: Reader): UpdateStory; + } export class UpdateReadStories extends VirtualClass<{ peer: Api.TypePeer; maxId: int; }> { peer: Api.TypePeer; maxId: int; - }; + static fromReader(reader: Reader): UpdateReadStories; + } export class UpdateStoryID extends VirtualClass<{ id: int; randomId: long; }> { id: int; randomId: long; - }; + static fromReader(reader: Reader): UpdateStoryID; + } export class UpdateStoriesStealthMode extends VirtualClass<{ stealthMode: Api.TypeStoriesStealthMode; }> { stealthMode: Api.TypeStoriesStealthMode; - }; + static fromReader(reader: Reader): UpdateStoriesStealthMode; + } export class UpdateSentStoryReaction extends VirtualClass<{ peer: Api.TypePeer; storyId: int; @@ -3844,7 +4222,8 @@ namespace Api { peer: Api.TypePeer; storyId: int; reaction: Api.TypeReaction; - }; + static fromReader(reader: Reader): UpdateSentStoryReaction; + } export class UpdateBotChatBoost extends VirtualClass<{ peer: Api.TypePeer; boost: Api.TypeBoost; @@ -3853,25 +4232,28 @@ namespace Api { peer: Api.TypePeer; boost: Api.TypeBoost; qts: int; - }; + static fromReader(reader: Reader): UpdateBotChatBoost; + } export class UpdateChannelViewForumAsMessages extends VirtualClass<{ channelId: long; enabled: Bool; }> { channelId: long; enabled: Bool; - }; + static fromReader(reader: Reader): UpdateChannelViewForumAsMessages; + } export class UpdatePeerWallpaper extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; wallpaperOverridden?: true; peer: Api.TypePeer; wallpaper?: Api.TypeWallPaper; }> { - // flags: undefined; + // flags: Api.Type; wallpaperOverridden?: true; peer: Api.TypePeer; wallpaper?: Api.TypeWallPaper; - }; + static fromReader(reader: Reader): UpdatePeerWallpaper; + } export class UpdateBotMessageReaction extends VirtualClass<{ peer: Api.TypePeer; msgId: int; @@ -3888,7 +4270,8 @@ namespace Api { oldReactions: Api.TypeReaction[]; newReactions: Api.TypeReaction[]; qts: int; - }; + static fromReader(reader: Reader): UpdateBotMessageReaction; + } export class UpdateBotMessageReactions extends VirtualClass<{ peer: Api.TypePeer; msgId: int; @@ -3901,89 +4284,103 @@ namespace Api { date: int; reactions: Api.TypeReactionCount[]; qts: int; - }; + static fromReader(reader: Reader): UpdateBotMessageReactions; + } export class UpdateSavedDialogPinned extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; pinned?: true; peer: Api.TypeDialogPeer; }> { - // flags: undefined; + // flags: Api.Type; pinned?: true; peer: Api.TypeDialogPeer; - }; + static fromReader(reader: Reader): UpdateSavedDialogPinned; + } export class UpdatePinnedSavedDialogs extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; order?: Api.TypeDialogPeer[]; } | void> { - // flags: undefined; + // flags: Api.Type; order?: Api.TypeDialogPeer[]; - }; - export class UpdateSavedReactionTags extends VirtualClass {}; + static fromReader(reader: Reader): UpdatePinnedSavedDialogs; + } + export class UpdateSavedReactionTags extends VirtualClass { + static fromReader(reader: Reader): UpdateSavedReactionTags; + } export class UpdateSmsJob extends VirtualClass<{ jobId: string; }> { jobId: string; - }; + static fromReader(reader: Reader): UpdateSmsJob; + } export class UpdateQuickReplies extends VirtualClass<{ quickReplies: Api.TypeQuickReply[]; }> { quickReplies: Api.TypeQuickReply[]; - }; + static fromReader(reader: Reader): UpdateQuickReplies; + } export class UpdateNewQuickReply extends VirtualClass<{ quickReply: Api.TypeQuickReply; }> { quickReply: Api.TypeQuickReply; - }; + static fromReader(reader: Reader): UpdateNewQuickReply; + } export class UpdateDeleteQuickReply extends VirtualClass<{ shortcutId: int; }> { shortcutId: int; - }; + static fromReader(reader: Reader): UpdateDeleteQuickReply; + } export class UpdateQuickReplyMessage extends VirtualClass<{ message: Api.TypeMessage; }> { message: Api.TypeMessage; - }; + static fromReader(reader: Reader): UpdateQuickReplyMessage; + } export class UpdateDeleteQuickReplyMessages extends VirtualClass<{ shortcutId: int; messages: int[]; }> { shortcutId: int; messages: int[]; - }; + static fromReader(reader: Reader): UpdateDeleteQuickReplyMessages; + } export class UpdateBotBusinessConnect extends VirtualClass<{ connection: Api.TypeBotBusinessConnection; qts: int; }> { connection: Api.TypeBotBusinessConnection; qts: int; - }; + static fromReader(reader: Reader): UpdateBotBusinessConnect; + } export class UpdateBotNewBusinessMessage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; connectionId: string; message: Api.TypeMessage; replyToMessage?: Api.TypeMessage; qts: int; }> { - // flags: undefined; + // flags: Api.Type; connectionId: string; message: Api.TypeMessage; replyToMessage?: Api.TypeMessage; qts: int; - }; + static fromReader(reader: Reader): UpdateBotNewBusinessMessage; + } export class UpdateBotEditBusinessMessage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; connectionId: string; message: Api.TypeMessage; replyToMessage?: Api.TypeMessage; qts: int; }> { - // flags: undefined; + // flags: Api.Type; connectionId: string; message: Api.TypeMessage; replyToMessage?: Api.TypeMessage; qts: int; - }; + static fromReader(reader: Reader): UpdateBotEditBusinessMessage; + } export class UpdateBotDeleteBusinessMessage extends VirtualClass<{ connectionId: string; peer: Api.TypePeer; @@ -3994,7 +4391,8 @@ namespace Api { peer: Api.TypePeer; messages: int[]; qts: int; - }; + static fromReader(reader: Reader): UpdateBotDeleteBusinessMessage; + } export class UpdateNewStoryReaction extends VirtualClass<{ storyId: int; peer: Api.TypePeer; @@ -4003,21 +4401,24 @@ namespace Api { storyId: int; peer: Api.TypePeer; reaction: Api.TypeReaction; - }; + static fromReader(reader: Reader): UpdateNewStoryReaction; + } export class UpdateBroadcastRevenueTransactions extends VirtualClass<{ peer: Api.TypePeer; balances: Api.TypeBroadcastRevenueBalances; }> { peer: Api.TypePeer; balances: Api.TypeBroadcastRevenueBalances; - }; + static fromReader(reader: Reader): UpdateBroadcastRevenueTransactions; + } export class UpdateStarsBalance extends VirtualClass<{ balance: Api.TypeStarsAmount; }> { balance: Api.TypeStarsAmount; - }; + static fromReader(reader: Reader): UpdateStarsBalance; + } export class UpdateBusinessBotCallbackQuery extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; queryId: long; userId: long; connectionId: string; @@ -4026,7 +4427,7 @@ namespace Api { chatInstance: long; data?: bytes; }> { - // flags: undefined; + // flags: Api.Type; queryId: long; userId: long; connectionId: string; @@ -4034,14 +4435,16 @@ namespace Api { replyToMessage?: Api.TypeMessage; chatInstance: long; data?: bytes; - }; + static fromReader(reader: Reader): UpdateBusinessBotCallbackQuery; + } export class UpdateStarsRevenueStatus extends VirtualClass<{ peer: Api.TypePeer; status: Api.TypeStarsRevenueStatus; }> { peer: Api.TypePeer; status: Api.TypeStarsRevenueStatus; - }; + static fromReader(reader: Reader): UpdateStarsRevenueStatus; + } export class UpdateBotPurchasedPaidMedia extends VirtualClass<{ userId: long; payload: string; @@ -4050,15 +4453,19 @@ namespace Api { userId: long; payload: string; qts: int; - }; + static fromReader(reader: Reader): UpdateBotPurchasedPaidMedia; + } export class UpdatePaidReactionPrivacy extends VirtualClass<{ private: Bool; }> { private: Bool; - }; - export class UpdatesTooLong extends VirtualClass {}; + static fromReader(reader: Reader): UpdatePaidReactionPrivacy; + } + export class UpdatesTooLong extends VirtualClass { + static fromReader(reader: Reader): UpdatesTooLong; + } export class UpdateShortMessage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; out?: true; mentioned?: true; mediaUnread?: true; @@ -4075,7 +4482,7 @@ namespace Api { entities?: Api.TypeMessageEntity[]; ttlPeriod?: int; }> { - // flags: undefined; + // flags: Api.Type; out?: true; mentioned?: true; mediaUnread?: true; @@ -4091,9 +4498,10 @@ namespace Api { replyTo?: Api.TypeMessageReplyHeader; entities?: Api.TypeMessageEntity[]; ttlPeriod?: int; - }; + static fromReader(reader: Reader): UpdateShortMessage; + } export class UpdateShortChatMessage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; out?: true; mentioned?: true; mediaUnread?: true; @@ -4111,7 +4519,7 @@ namespace Api { entities?: Api.TypeMessageEntity[]; ttlPeriod?: int; }> { - // flags: undefined; + // flags: Api.Type; out?: true; mentioned?: true; mediaUnread?: true; @@ -4128,14 +4536,16 @@ namespace Api { replyTo?: Api.TypeMessageReplyHeader; entities?: Api.TypeMessageEntity[]; ttlPeriod?: int; - }; + static fromReader(reader: Reader): UpdateShortChatMessage; + } export class UpdateShort extends VirtualClass<{ update: Api.TypeUpdate; date: int; }> { update: Api.TypeUpdate; date: int; - }; + static fromReader(reader: Reader): UpdateShort; + } export class UpdatesCombined extends VirtualClass<{ updates: Api.TypeUpdate[]; users: Api.TypeUser[]; @@ -4150,7 +4560,8 @@ namespace Api { date: int; seqStart: int; seq: int; - }; + static fromReader(reader: Reader): UpdatesCombined; + } export class Updates extends VirtualClass<{ updates: Api.TypeUpdate[]; users: Api.TypeUser[]; @@ -4163,9 +4574,10 @@ namespace Api { chats: Api.TypeChat[]; date: int; seq: int; - }; + static fromReader(reader: Reader): Updates; + } export class UpdateShortSentMessage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; out?: true; id: int; pts: int; @@ -4175,7 +4587,7 @@ namespace Api { entities?: Api.TypeMessageEntity[]; ttlPeriod?: int; }> { - // flags: undefined; + // flags: Api.Type; out?: true; id: int; pts: int; @@ -4184,9 +4596,10 @@ namespace Api { media?: Api.TypeMessageMedia; entities?: Api.TypeMessageEntity[]; ttlPeriod?: int; - }; + static fromReader(reader: Reader): UpdateShortSentMessage; + } export class DcOption extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; ipv6?: true; mediaOnly?: true; tcpoOnly?: true; @@ -4198,7 +4611,7 @@ namespace Api { port: int; secret?: bytes; }> { - // flags: undefined; + // flags: Api.Type; ipv6?: true; mediaOnly?: true; tcpoOnly?: true; @@ -4209,9 +4622,10 @@ namespace Api { ipAddress: string; port: int; secret?: bytes; - }; + static fromReader(reader: Reader): DcOption; + } export class Config extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; defaultP2pContacts?: true; preloadFeaturedStickers?: true; revokePmInbox?: true; @@ -4260,7 +4674,7 @@ namespace Api { reactionsDefault?: Api.TypeReaction; autologinToken?: string; }> { - // flags: undefined; + // flags: Api.Type; defaultP2pContacts?: true; preloadFeaturedStickers?: true; revokePmInbox?: true; @@ -4308,7 +4722,8 @@ namespace Api { baseLangPackVersion?: int; reactionsDefault?: Api.TypeReaction; autologinToken?: string; - }; + static fromReader(reader: Reader): Config; + } export class NearestDc extends VirtualClass<{ country: string; thisDc: int; @@ -4317,12 +4732,14 @@ namespace Api { country: string; thisDc: int; nearestDc: int; - }; + static fromReader(reader: Reader): NearestDc; + } export class EncryptedChatEmpty extends VirtualClass<{ id: int; }> { id: int; - }; + static fromReader(reader: Reader): EncryptedChatEmpty; + } export class EncryptedChatWaiting extends VirtualClass<{ id: int; accessHash: long; @@ -4335,9 +4752,10 @@ namespace Api { date: int; adminId: long; participantId: long; - }; + static fromReader(reader: Reader): EncryptedChatWaiting; + } export class EncryptedChatRequested extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; folderId?: int; id: int; accessHash: long; @@ -4346,7 +4764,7 @@ namespace Api { participantId: long; gA: bytes; }> { - // flags: undefined; + // flags: Api.Type; folderId?: int; id: int; accessHash: long; @@ -4354,7 +4772,8 @@ namespace Api { adminId: long; participantId: long; gA: bytes; - }; + static fromReader(reader: Reader): EncryptedChatRequested; + } export class EncryptedChat extends VirtualClass<{ id: int; accessHash: long; @@ -4371,24 +4790,29 @@ namespace Api { participantId: long; gAOrB: bytes; keyFingerprint: long; - }; + static fromReader(reader: Reader): EncryptedChat; + } export class EncryptedChatDiscarded extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; historyDeleted?: true; id: int; }> { - // flags: undefined; + // flags: Api.Type; historyDeleted?: true; id: int; - }; + static fromReader(reader: Reader): EncryptedChatDiscarded; + } export class InputEncryptedChat extends VirtualClass<{ chatId: int; accessHash: long; }> { chatId: int; accessHash: long; - }; - export class EncryptedFileEmpty extends VirtualClass {}; + static fromReader(reader: Reader): InputEncryptedChat; + } + export class EncryptedFileEmpty extends VirtualClass { + static fromReader(reader: Reader): EncryptedFileEmpty; + } export class EncryptedFile extends VirtualClass<{ id: long; accessHash: long; @@ -4401,8 +4825,11 @@ namespace Api { size: long; dcId: int; keyFingerprint: int; - }; - export class InputEncryptedFileEmpty extends VirtualClass {}; + static fromReader(reader: Reader): EncryptedFile; + } + export class InputEncryptedFileEmpty extends VirtualClass { + static fromReader(reader: Reader): InputEncryptedFileEmpty; + } export class InputEncryptedFileUploaded extends VirtualClass<{ id: long; parts: int; @@ -4413,14 +4840,16 @@ namespace Api { parts: int; md5Checksum: string; keyFingerprint: int; - }; + static fromReader(reader: Reader): InputEncryptedFileUploaded; + } export class InputEncryptedFile extends VirtualClass<{ id: long; accessHash: long; }> { id: long; accessHash: long; - }; + static fromReader(reader: Reader): InputEncryptedFile; + } export class InputEncryptedFileBigUploaded extends VirtualClass<{ id: long; parts: int; @@ -4429,7 +4858,8 @@ namespace Api { id: long; parts: int; keyFingerprint: int; - }; + static fromReader(reader: Reader): InputEncryptedFileBigUploaded; + } export class EncryptedMessage extends VirtualClass<{ randomId: long; chatId: int; @@ -4442,7 +4872,8 @@ namespace Api { date: int; bytes: bytes; file: Api.TypeEncryptedFile; - }; + static fromReader(reader: Reader): EncryptedMessage; + } export class EncryptedMessageService extends VirtualClass<{ randomId: long; chatId: int; @@ -4453,8 +4884,11 @@ namespace Api { chatId: int; date: int; bytes: bytes; - }; - export class InputDocumentEmpty extends VirtualClass {}; + static fromReader(reader: Reader): EncryptedMessageService; + } + export class InputDocumentEmpty extends VirtualClass { + static fromReader(reader: Reader): InputDocumentEmpty; + } export class InputDocument extends VirtualClass<{ id: long; accessHash: long; @@ -4463,14 +4897,16 @@ namespace Api { id: long; accessHash: long; fileReference: bytes; - }; + static fromReader(reader: Reader): InputDocument; + } export class DocumentEmpty extends VirtualClass<{ id: long; }> { id: long; - }; + static fromReader(reader: Reader): DocumentEmpty; + } export class Document extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; id: long; accessHash: long; fileReference: bytes; @@ -4482,7 +4918,7 @@ namespace Api { dcId: int; attributes: Api.TypeDocumentAttribute[]; }> { - // flags: undefined; + // flags: Api.Type; id: long; accessHash: long; fileReference: bytes; @@ -4493,62 +4929,97 @@ namespace Api { videoThumbs?: Api.TypeVideoSize[]; dcId: int; attributes: Api.TypeDocumentAttribute[]; - }; + static fromReader(reader: Reader): Document; + } export class NotifyPeer extends VirtualClass<{ peer: Api.TypePeer; }> { peer: Api.TypePeer; - }; - export class NotifyUsers extends VirtualClass {}; - export class NotifyChats extends VirtualClass {}; - export class NotifyBroadcasts extends VirtualClass {}; + static fromReader(reader: Reader): NotifyPeer; + } + export class NotifyUsers extends VirtualClass { + static fromReader(reader: Reader): NotifyUsers; + } + export class NotifyChats extends VirtualClass { + static fromReader(reader: Reader): NotifyChats; + } + export class NotifyBroadcasts extends VirtualClass { + static fromReader(reader: Reader): NotifyBroadcasts; + } export class NotifyForumTopic extends VirtualClass<{ peer: Api.TypePeer; topMsgId: int; }> { peer: Api.TypePeer; topMsgId: int; - }; - export class SendMessageTypingAction extends VirtualClass {}; - export class SendMessageCancelAction extends VirtualClass {}; - export class SendMessageRecordVideoAction extends VirtualClass {}; + static fromReader(reader: Reader): NotifyForumTopic; + } + export class SendMessageTypingAction extends VirtualClass { + static fromReader(reader: Reader): SendMessageTypingAction; + } + export class SendMessageCancelAction extends VirtualClass { + static fromReader(reader: Reader): SendMessageCancelAction; + } + export class SendMessageRecordVideoAction extends VirtualClass { + static fromReader(reader: Reader): SendMessageRecordVideoAction; + } export class SendMessageUploadVideoAction extends VirtualClass<{ progress: int; }> { progress: int; - }; - export class SendMessageRecordAudioAction extends VirtualClass {}; + static fromReader(reader: Reader): SendMessageUploadVideoAction; + } + export class SendMessageRecordAudioAction extends VirtualClass { + static fromReader(reader: Reader): SendMessageRecordAudioAction; + } export class SendMessageUploadAudioAction extends VirtualClass<{ progress: int; }> { progress: int; - }; + static fromReader(reader: Reader): SendMessageUploadAudioAction; + } export class SendMessageUploadPhotoAction extends VirtualClass<{ progress: int; }> { progress: int; - }; + static fromReader(reader: Reader): SendMessageUploadPhotoAction; + } export class SendMessageUploadDocumentAction extends VirtualClass<{ progress: int; }> { progress: int; - }; - export class SendMessageGeoLocationAction extends VirtualClass {}; - export class SendMessageChooseContactAction extends VirtualClass {}; - export class SendMessageGamePlayAction extends VirtualClass {}; - export class SendMessageRecordRoundAction extends VirtualClass {}; + static fromReader(reader: Reader): SendMessageUploadDocumentAction; + } + export class SendMessageGeoLocationAction extends VirtualClass { + static fromReader(reader: Reader): SendMessageGeoLocationAction; + } + export class SendMessageChooseContactAction extends VirtualClass { + static fromReader(reader: Reader): SendMessageChooseContactAction; + } + export class SendMessageGamePlayAction extends VirtualClass { + static fromReader(reader: Reader): SendMessageGamePlayAction; + } + export class SendMessageRecordRoundAction extends VirtualClass { + static fromReader(reader: Reader): SendMessageRecordRoundAction; + } export class SendMessageUploadRoundAction extends VirtualClass<{ progress: int; }> { progress: int; - }; - export class SpeakingInGroupCallAction extends VirtualClass {}; + static fromReader(reader: Reader): SendMessageUploadRoundAction; + } + export class SpeakingInGroupCallAction extends VirtualClass { + static fromReader(reader: Reader): SpeakingInGroupCallAction; + } export class SendMessageHistoryImportAction extends VirtualClass<{ progress: int; }> { progress: int; - }; - export class SendMessageChooseStickerAction extends VirtualClass {}; + static fromReader(reader: Reader): SendMessageHistoryImportAction; + } + export class SendMessageChooseStickerAction extends VirtualClass { + static fromReader(reader: Reader): SendMessageChooseStickerAction; + } export class SendMessageEmojiInteraction extends VirtualClass<{ emoticon: string; msgId: int; @@ -4557,120 +5028,215 @@ namespace Api { emoticon: string; msgId: int; interaction: Api.TypeDataJSON; - }; + static fromReader(reader: Reader): SendMessageEmojiInteraction; + } export class SendMessageEmojiInteractionSeen extends VirtualClass<{ emoticon: string; }> { emoticon: string; - }; - export class InputPrivacyKeyStatusTimestamp extends VirtualClass {}; - export class InputPrivacyKeyChatInvite extends VirtualClass {}; - export class InputPrivacyKeyPhoneCall extends VirtualClass {}; - export class InputPrivacyKeyPhoneP2P extends VirtualClass {}; - export class InputPrivacyKeyForwards extends VirtualClass {}; - export class InputPrivacyKeyProfilePhoto extends VirtualClass {}; - export class InputPrivacyKeyPhoneNumber extends VirtualClass {}; - export class InputPrivacyKeyAddedByPhone extends VirtualClass {}; - export class InputPrivacyKeyVoiceMessages extends VirtualClass {}; - export class InputPrivacyKeyAbout extends VirtualClass {}; - export class InputPrivacyKeyBirthday extends VirtualClass {}; - export class InputPrivacyKeyStarGiftsAutoSave extends VirtualClass {}; - export class PrivacyKeyStatusTimestamp extends VirtualClass {}; - export class PrivacyKeyChatInvite extends VirtualClass {}; - export class PrivacyKeyPhoneCall extends VirtualClass {}; - export class PrivacyKeyPhoneP2P extends VirtualClass {}; - export class PrivacyKeyForwards extends VirtualClass {}; - export class PrivacyKeyProfilePhoto extends VirtualClass {}; - export class PrivacyKeyPhoneNumber extends VirtualClass {}; - export class PrivacyKeyAddedByPhone extends VirtualClass {}; - export class PrivacyKeyVoiceMessages extends VirtualClass {}; - export class PrivacyKeyAbout extends VirtualClass {}; - export class PrivacyKeyBirthday extends VirtualClass {}; - export class PrivacyKeyStarGiftsAutoSave extends VirtualClass {}; - export class InputPrivacyValueAllowContacts extends VirtualClass {}; - export class InputPrivacyValueAllowAll extends VirtualClass {}; + static fromReader(reader: Reader): SendMessageEmojiInteractionSeen; + } + export class InputPrivacyKeyStatusTimestamp extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyKeyStatusTimestamp; + } + export class InputPrivacyKeyChatInvite extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyKeyChatInvite; + } + export class InputPrivacyKeyPhoneCall extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyKeyPhoneCall; + } + export class InputPrivacyKeyPhoneP2P extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyKeyPhoneP2P; + } + export class InputPrivacyKeyForwards extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyKeyForwards; + } + export class InputPrivacyKeyProfilePhoto extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyKeyProfilePhoto; + } + export class InputPrivacyKeyPhoneNumber extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyKeyPhoneNumber; + } + export class InputPrivacyKeyAddedByPhone extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyKeyAddedByPhone; + } + export class InputPrivacyKeyVoiceMessages extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyKeyVoiceMessages; + } + export class InputPrivacyKeyAbout extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyKeyAbout; + } + export class InputPrivacyKeyBirthday extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyKeyBirthday; + } + export class InputPrivacyKeyStarGiftsAutoSave extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyKeyStarGiftsAutoSave; + } + export class PrivacyKeyStatusTimestamp extends VirtualClass { + static fromReader(reader: Reader): PrivacyKeyStatusTimestamp; + } + export class PrivacyKeyChatInvite extends VirtualClass { + static fromReader(reader: Reader): PrivacyKeyChatInvite; + } + export class PrivacyKeyPhoneCall extends VirtualClass { + static fromReader(reader: Reader): PrivacyKeyPhoneCall; + } + export class PrivacyKeyPhoneP2P extends VirtualClass { + static fromReader(reader: Reader): PrivacyKeyPhoneP2P; + } + export class PrivacyKeyForwards extends VirtualClass { + static fromReader(reader: Reader): PrivacyKeyForwards; + } + export class PrivacyKeyProfilePhoto extends VirtualClass { + static fromReader(reader: Reader): PrivacyKeyProfilePhoto; + } + export class PrivacyKeyPhoneNumber extends VirtualClass { + static fromReader(reader: Reader): PrivacyKeyPhoneNumber; + } + export class PrivacyKeyAddedByPhone extends VirtualClass { + static fromReader(reader: Reader): PrivacyKeyAddedByPhone; + } + export class PrivacyKeyVoiceMessages extends VirtualClass { + static fromReader(reader: Reader): PrivacyKeyVoiceMessages; + } + export class PrivacyKeyAbout extends VirtualClass { + static fromReader(reader: Reader): PrivacyKeyAbout; + } + export class PrivacyKeyBirthday extends VirtualClass { + static fromReader(reader: Reader): PrivacyKeyBirthday; + } + export class PrivacyKeyStarGiftsAutoSave extends VirtualClass { + static fromReader(reader: Reader): PrivacyKeyStarGiftsAutoSave; + } + export class InputPrivacyValueAllowContacts extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyValueAllowContacts; + } + export class InputPrivacyValueAllowAll extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyValueAllowAll; + } export class InputPrivacyValueAllowUsers extends VirtualClass<{ users: Api.TypeInputUser[]; }> { users: Api.TypeInputUser[]; - }; - export class InputPrivacyValueDisallowContacts extends VirtualClass {}; - export class InputPrivacyValueDisallowAll extends VirtualClass {}; + static fromReader(reader: Reader): InputPrivacyValueAllowUsers; + } + export class InputPrivacyValueDisallowContacts extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyValueDisallowContacts; + } + export class InputPrivacyValueDisallowAll extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyValueDisallowAll; + } export class InputPrivacyValueDisallowUsers extends VirtualClass<{ users: Api.TypeInputUser[]; }> { users: Api.TypeInputUser[]; - }; + static fromReader(reader: Reader): InputPrivacyValueDisallowUsers; + } export class InputPrivacyValueAllowChatParticipants extends VirtualClass<{ chats: long[]; }> { chats: long[]; - }; + static fromReader(reader: Reader): InputPrivacyValueAllowChatParticipants; + } export class InputPrivacyValueDisallowChatParticipants extends VirtualClass<{ chats: long[]; }> { chats: long[]; - }; - export class InputPrivacyValueAllowCloseFriends extends VirtualClass {}; - export class InputPrivacyValueAllowPremium extends VirtualClass {}; - export class InputPrivacyValueAllowBots extends VirtualClass {}; - export class InputPrivacyValueDisallowBots extends VirtualClass {}; - export class PrivacyValueAllowContacts extends VirtualClass {}; - export class PrivacyValueAllowAll extends VirtualClass {}; + static fromReader(reader: Reader): InputPrivacyValueDisallowChatParticipants; + } + export class InputPrivacyValueAllowCloseFriends extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyValueAllowCloseFriends; + } + export class InputPrivacyValueAllowPremium extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyValueAllowPremium; + } + export class InputPrivacyValueAllowBots extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyValueAllowBots; + } + export class InputPrivacyValueDisallowBots extends VirtualClass { + static fromReader(reader: Reader): InputPrivacyValueDisallowBots; + } + export class PrivacyValueAllowContacts extends VirtualClass { + static fromReader(reader: Reader): PrivacyValueAllowContacts; + } + export class PrivacyValueAllowAll extends VirtualClass { + static fromReader(reader: Reader): PrivacyValueAllowAll; + } export class PrivacyValueAllowUsers extends VirtualClass<{ users: long[]; }> { users: long[]; - }; - export class PrivacyValueDisallowContacts extends VirtualClass {}; - export class PrivacyValueDisallowAll extends VirtualClass {}; + static fromReader(reader: Reader): PrivacyValueAllowUsers; + } + export class PrivacyValueDisallowContacts extends VirtualClass { + static fromReader(reader: Reader): PrivacyValueDisallowContacts; + } + export class PrivacyValueDisallowAll extends VirtualClass { + static fromReader(reader: Reader): PrivacyValueDisallowAll; + } export class PrivacyValueDisallowUsers extends VirtualClass<{ users: long[]; }> { users: long[]; - }; + static fromReader(reader: Reader): PrivacyValueDisallowUsers; + } export class PrivacyValueAllowChatParticipants extends VirtualClass<{ chats: long[]; }> { chats: long[]; - }; + static fromReader(reader: Reader): PrivacyValueAllowChatParticipants; + } export class PrivacyValueDisallowChatParticipants extends VirtualClass<{ chats: long[]; }> { chats: long[]; - }; - export class PrivacyValueAllowCloseFriends extends VirtualClass {}; - export class PrivacyValueAllowPremium extends VirtualClass {}; - export class PrivacyValueAllowBots extends VirtualClass {}; - export class PrivacyValueDisallowBots extends VirtualClass {}; + static fromReader(reader: Reader): PrivacyValueDisallowChatParticipants; + } + export class PrivacyValueAllowCloseFriends extends VirtualClass { + static fromReader(reader: Reader): PrivacyValueAllowCloseFriends; + } + export class PrivacyValueAllowPremium extends VirtualClass { + static fromReader(reader: Reader): PrivacyValueAllowPremium; + } + export class PrivacyValueAllowBots extends VirtualClass { + static fromReader(reader: Reader): PrivacyValueAllowBots; + } + export class PrivacyValueDisallowBots extends VirtualClass { + static fromReader(reader: Reader): PrivacyValueDisallowBots; + } export class AccountDaysTTL extends VirtualClass<{ days: int; }> { days: int; - }; + static fromReader(reader: Reader): AccountDaysTTL; + } export class DocumentAttributeImageSize extends VirtualClass<{ w: int; h: int; }> { w: int; h: int; - }; - export class DocumentAttributeAnimated extends VirtualClass {}; + static fromReader(reader: Reader): DocumentAttributeImageSize; + } + export class DocumentAttributeAnimated extends VirtualClass { + static fromReader(reader: Reader): DocumentAttributeAnimated; + } export class DocumentAttributeSticker extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; mask?: true; alt: string; stickerset: Api.TypeInputStickerSet; maskCoords?: Api.TypeMaskCoords; }> { - // flags: undefined; + // flags: Api.Type; mask?: true; alt: string; stickerset: Api.TypeInputStickerSet; maskCoords?: Api.TypeMaskCoords; - }; + static fromReader(reader: Reader): DocumentAttributeSticker; + } export class DocumentAttributeVideo extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; roundMessage?: true; supportsStreaming?: true; nosound?: true; @@ -4681,7 +5247,7 @@ namespace Api { videoStartTs?: double; videoCodec?: string; }> { - // flags: undefined; + // flags: Api.Type; roundMessage?: true; supportsStreaming?: true; nosound?: true; @@ -4691,70 +5257,79 @@ namespace Api { preloadPrefixSize?: int; videoStartTs?: double; videoCodec?: string; - }; + static fromReader(reader: Reader): DocumentAttributeVideo; + } export class DocumentAttributeAudio extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; voice?: true; duration: int; title?: string; performer?: string; waveform?: bytes; }> { - // flags: undefined; + // flags: Api.Type; voice?: true; duration: int; title?: string; performer?: string; waveform?: bytes; - }; + static fromReader(reader: Reader): DocumentAttributeAudio; + } export class DocumentAttributeFilename extends VirtualClass<{ fileName: string; }> { fileName: string; - }; - export class DocumentAttributeHasStickers extends VirtualClass {}; + static fromReader(reader: Reader): DocumentAttributeFilename; + } + export class DocumentAttributeHasStickers extends VirtualClass { + static fromReader(reader: Reader): DocumentAttributeHasStickers; + } export class DocumentAttributeCustomEmoji extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; free?: true; textColor?: true; alt: string; stickerset: Api.TypeInputStickerSet; }> { - // flags: undefined; + // flags: Api.Type; free?: true; textColor?: true; alt: string; stickerset: Api.TypeInputStickerSet; - }; + static fromReader(reader: Reader): DocumentAttributeCustomEmoji; + } export class StickerPack extends VirtualClass<{ emoticon: string; documents: long[]; }> { emoticon: string; documents: long[]; - }; + static fromReader(reader: Reader): StickerPack; + } export class WebPageEmpty extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; id: long; url?: string; }> { - // flags: undefined; + // flags: Api.Type; id: long; url?: string; - }; + static fromReader(reader: Reader): WebPageEmpty; + } export class WebPagePending extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; id: long; url?: string; date: int; }> { - // flags: undefined; + // flags: Api.Type; id: long; url?: string; date: int; - }; + static fromReader(reader: Reader): WebPagePending; + } export class WebPage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; hasLargeMedia?: true; id: long; url: string; @@ -4775,7 +5350,7 @@ namespace Api { cachedPage?: Api.TypePage; attributes?: Api.TypeWebPageAttribute[]; }> { - // flags: undefined; + // flags: Api.Type; hasLargeMedia?: true; id: long; url: string; @@ -4795,16 +5370,18 @@ namespace Api { document?: Api.TypeDocument; cachedPage?: Api.TypePage; attributes?: Api.TypeWebPageAttribute[]; - }; + static fromReader(reader: Reader): WebPage; + } export class WebPageNotModified extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; cachedPageViews?: int; } | void> { - // flags: undefined; + // flags: Api.Type; cachedPageViews?: int; - }; + static fromReader(reader: Reader): WebPageNotModified; + } export class Authorization extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; current?: true; officialApp?: true; passwordPending?: true; @@ -4824,7 +5401,7 @@ namespace Api { country: string; region: string; }> { - // flags: undefined; + // flags: Api.Type; current?: true; officialApp?: true; passwordPending?: true; @@ -4843,16 +5420,18 @@ namespace Api { ip: string; country: string; region: string; - }; + static fromReader(reader: Reader): Authorization; + } export class ReceivedNotifyMessage extends VirtualClass<{ id: int; // flags: int; }> { id: int; // flags: int; - }; + static fromReader(reader: Reader): ReceivedNotifyMessage; + } export class ChatInviteExported extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; revoked?: true; permanent?: true; requestNeeded?: true; @@ -4868,7 +5447,7 @@ namespace Api { title?: string; subscriptionPricing?: Api.TypeStarsSubscriptionPricing; }> { - // flags: undefined; + // flags: Api.Type; revoked?: true; permanent?: true; requestNeeded?: true; @@ -4883,15 +5462,19 @@ namespace Api { subscriptionExpired?: int; title?: string; subscriptionPricing?: Api.TypeStarsSubscriptionPricing; - }; - export class ChatInvitePublicJoinRequests extends VirtualClass {}; + static fromReader(reader: Reader): ChatInviteExported; + } + export class ChatInvitePublicJoinRequests extends VirtualClass { + static fromReader(reader: Reader): ChatInvitePublicJoinRequests; + } export class ChatInviteAlready extends VirtualClass<{ chat: Api.TypeChat; }> { chat: Api.TypeChat; - }; + static fromReader(reader: Reader): ChatInviteAlready; + } export class ChatInvite extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; channel?: true; broadcast?: true; public?: true; @@ -4911,7 +5494,7 @@ namespace Api { subscriptionFormId?: long; botVerification?: Api.TypeBotVerification; }> { - // flags: undefined; + // flags: Api.Type; channel?: true; broadcast?: true; public?: true; @@ -4930,41 +5513,62 @@ namespace Api { subscriptionPricing?: Api.TypeStarsSubscriptionPricing; subscriptionFormId?: long; botVerification?: Api.TypeBotVerification; - }; + static fromReader(reader: Reader): ChatInvite; + } export class ChatInvitePeek extends VirtualClass<{ chat: Api.TypeChat; expires: int; }> { chat: Api.TypeChat; expires: int; - }; - export class InputStickerSetEmpty extends VirtualClass {}; + static fromReader(reader: Reader): ChatInvitePeek; + } + export class InputStickerSetEmpty extends VirtualClass { + static fromReader(reader: Reader): InputStickerSetEmpty; + } export class InputStickerSetID extends VirtualClass<{ id: long; accessHash: long; }> { id: long; accessHash: long; - }; + static fromReader(reader: Reader): InputStickerSetID; + } export class InputStickerSetShortName extends VirtualClass<{ shortName: string; }> { shortName: string; - }; - export class InputStickerSetAnimatedEmoji extends VirtualClass {}; + static fromReader(reader: Reader): InputStickerSetShortName; + } + export class InputStickerSetAnimatedEmoji extends VirtualClass { + static fromReader(reader: Reader): InputStickerSetAnimatedEmoji; + } export class InputStickerSetDice extends VirtualClass<{ emoticon: string; }> { emoticon: string; - }; - export class InputStickerSetAnimatedEmojiAnimations extends VirtualClass {}; - export class InputStickerSetPremiumGifts extends VirtualClass {}; - export class InputStickerSetEmojiGenericAnimations extends VirtualClass {}; - export class InputStickerSetEmojiDefaultStatuses extends VirtualClass {}; - export class InputStickerSetEmojiDefaultTopicIcons extends VirtualClass {}; - export class InputStickerSetEmojiChannelDefaultStatuses extends VirtualClass {}; + static fromReader(reader: Reader): InputStickerSetDice; + } + export class InputStickerSetAnimatedEmojiAnimations extends VirtualClass { + static fromReader(reader: Reader): InputStickerSetAnimatedEmojiAnimations; + } + export class InputStickerSetPremiumGifts extends VirtualClass { + static fromReader(reader: Reader): InputStickerSetPremiumGifts; + } + export class InputStickerSetEmojiGenericAnimations extends VirtualClass { + static fromReader(reader: Reader): InputStickerSetEmojiGenericAnimations; + } + export class InputStickerSetEmojiDefaultStatuses extends VirtualClass { + static fromReader(reader: Reader): InputStickerSetEmojiDefaultStatuses; + } + export class InputStickerSetEmojiDefaultTopicIcons extends VirtualClass { + static fromReader(reader: Reader): InputStickerSetEmojiDefaultTopicIcons; + } + export class InputStickerSetEmojiChannelDefaultStatuses extends VirtualClass { + static fromReader(reader: Reader): InputStickerSetEmojiChannelDefaultStatuses; + } export class StickerSet extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; archived?: true; official?: true; masks?: true; @@ -4984,7 +5588,7 @@ namespace Api { count: int; hash: int; }> { - // flags: undefined; + // flags: Api.Type; archived?: true; official?: true; masks?: true; @@ -5003,16 +5607,18 @@ namespace Api { thumbDocumentId?: long; count: int; hash: int; - }; + static fromReader(reader: Reader): StickerSet; + } export class BotCommand extends VirtualClass<{ command: string; description: string; }> { command: string; description: string; - }; + static fromReader(reader: Reader): BotCommand; + } export class BotInfo extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; hasPreviewMedias?: true; userId?: long; description?: string; @@ -5024,7 +5630,7 @@ namespace Api { appSettings?: Api.TypeBotAppSettings; verifierSettings?: Api.TypeBotVerifierSettings; } | void> { - // flags: undefined; + // flags: Api.Type; hasPreviewMedias?: true; userId?: long; description?: string; @@ -5035,128 +5641,144 @@ namespace Api { privacyPolicyUrl?: string; appSettings?: Api.TypeBotAppSettings; verifierSettings?: Api.TypeBotVerifierSettings; - }; + static fromReader(reader: Reader): BotInfo; + } export class KeyboardButton extends VirtualClass<{ text: string; }> { text: string; - }; + static fromReader(reader: Reader): KeyboardButton; + } export class KeyboardButtonUrl extends VirtualClass<{ text: string; url: string; }> { text: string; url: string; - }; + static fromReader(reader: Reader): KeyboardButtonUrl; + } export class KeyboardButtonCallback extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; requiresPassword?: true; text: string; data: bytes; }> { - // flags: undefined; + // flags: Api.Type; requiresPassword?: true; text: string; data: bytes; - }; + static fromReader(reader: Reader): KeyboardButtonCallback; + } export class KeyboardButtonRequestPhone extends VirtualClass<{ text: string; }> { text: string; - }; + static fromReader(reader: Reader): KeyboardButtonRequestPhone; + } export class KeyboardButtonRequestGeoLocation extends VirtualClass<{ text: string; }> { text: string; - }; + static fromReader(reader: Reader): KeyboardButtonRequestGeoLocation; + } export class KeyboardButtonSwitchInline extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; samePeer?: true; text: string; query: string; peerTypes?: Api.TypeInlineQueryPeerType[]; }> { - // flags: undefined; + // flags: Api.Type; samePeer?: true; text: string; query: string; peerTypes?: Api.TypeInlineQueryPeerType[]; - }; + static fromReader(reader: Reader): KeyboardButtonSwitchInline; + } export class KeyboardButtonGame extends VirtualClass<{ text: string; }> { text: string; - }; + static fromReader(reader: Reader): KeyboardButtonGame; + } export class KeyboardButtonBuy extends VirtualClass<{ text: string; }> { text: string; - }; + static fromReader(reader: Reader): KeyboardButtonBuy; + } export class KeyboardButtonUrlAuth extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; text: string; fwdText?: string; url: string; buttonId: int; }> { - // flags: undefined; + // flags: Api.Type; text: string; fwdText?: string; url: string; buttonId: int; - }; + static fromReader(reader: Reader): KeyboardButtonUrlAuth; + } export class InputKeyboardButtonUrlAuth extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; requestWriteAccess?: true; text: string; fwdText?: string; url: string; bot: Api.TypeInputUser; }> { - // flags: undefined; + // flags: Api.Type; requestWriteAccess?: true; text: string; fwdText?: string; url: string; bot: Api.TypeInputUser; - }; + static fromReader(reader: Reader): InputKeyboardButtonUrlAuth; + } export class KeyboardButtonRequestPoll extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; quiz?: Bool; text: string; }> { - // flags: undefined; + // flags: Api.Type; quiz?: Bool; text: string; - }; + static fromReader(reader: Reader): KeyboardButtonRequestPoll; + } export class InputKeyboardButtonUserProfile extends VirtualClass<{ text: string; userId: Api.TypeInputUser; }> { text: string; userId: Api.TypeInputUser; - }; + static fromReader(reader: Reader): InputKeyboardButtonUserProfile; + } export class KeyboardButtonUserProfile extends VirtualClass<{ text: string; userId: long; }> { text: string; userId: long; - }; + static fromReader(reader: Reader): KeyboardButtonUserProfile; + } export class KeyboardButtonWebView extends VirtualClass<{ text: string; url: string; }> { text: string; url: string; - }; + static fromReader(reader: Reader): KeyboardButtonWebView; + } export class KeyboardButtonSimpleWebView extends VirtualClass<{ text: string; url: string; }> { text: string; url: string; - }; + static fromReader(reader: Reader): KeyboardButtonSimpleWebView; + } export class KeyboardButtonRequestPeer extends VirtualClass<{ text: string; buttonId: int; @@ -5167,9 +5789,10 @@ namespace Api { buttonId: int; peerType: Api.TypeRequestPeerType; maxQuantity: int; - }; + static fromReader(reader: Reader): KeyboardButtonRequestPeer; + } export class InputKeyboardButtonRequestPeer extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; nameRequested?: true; usernameRequested?: true; photoRequested?: true; @@ -5178,7 +5801,7 @@ namespace Api { peerType: Api.TypeRequestPeerType; maxQuantity: int; }> { - // flags: undefined; + // flags: Api.Type; nameRequested?: true; usernameRequested?: true; photoRequested?: true; @@ -5186,39 +5809,44 @@ namespace Api { buttonId: int; peerType: Api.TypeRequestPeerType; maxQuantity: int; - }; + static fromReader(reader: Reader): InputKeyboardButtonRequestPeer; + } export class KeyboardButtonCopy extends VirtualClass<{ text: string; copyText: string; }> { text: string; copyText: string; - }; + static fromReader(reader: Reader): KeyboardButtonCopy; + } export class KeyboardButtonRow extends VirtualClass<{ buttons: Api.TypeKeyboardButton[]; }> { buttons: Api.TypeKeyboardButton[]; - }; + static fromReader(reader: Reader): KeyboardButtonRow; + } export class ReplyKeyboardHide extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; selective?: true; } | void> { - // flags: undefined; + // flags: Api.Type; selective?: true; - }; + static fromReader(reader: Reader): ReplyKeyboardHide; + } export class ReplyKeyboardForceReply extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; singleUse?: true; selective?: true; placeholder?: string; } | void> { - // flags: undefined; + // flags: Api.Type; singleUse?: true; selective?: true; placeholder?: string; - }; + static fromReader(reader: Reader): ReplyKeyboardForceReply; + } export class ReplyKeyboardMarkup extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; resize?: true; singleUse?: true; selective?: true; @@ -5226,82 +5854,93 @@ namespace Api { rows: Api.TypeKeyboardButtonRow[]; placeholder?: string; }> { - // flags: undefined; + // flags: Api.Type; resize?: true; singleUse?: true; selective?: true; persistent?: true; rows: Api.TypeKeyboardButtonRow[]; placeholder?: string; - }; + static fromReader(reader: Reader): ReplyKeyboardMarkup; + } export class ReplyInlineMarkup extends VirtualClass<{ rows: Api.TypeKeyboardButtonRow[]; }> { rows: Api.TypeKeyboardButtonRow[]; - }; + static fromReader(reader: Reader): ReplyInlineMarkup; + } export class MessageEntityUnknown extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntityUnknown; + } export class MessageEntityMention extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntityMention; + } export class MessageEntityHashtag extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntityHashtag; + } export class MessageEntityBotCommand extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntityBotCommand; + } export class MessageEntityUrl extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntityUrl; + } export class MessageEntityEmail extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntityEmail; + } export class MessageEntityBold extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntityBold; + } export class MessageEntityItalic extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntityItalic; + } export class MessageEntityCode extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntityCode; + } export class MessageEntityPre extends VirtualClass<{ offset: int; length: int; @@ -5310,7 +5949,8 @@ namespace Api { offset: int; length: int; language: string; - }; + static fromReader(reader: Reader): MessageEntityPre; + } export class MessageEntityTextUrl extends VirtualClass<{ offset: int; length: int; @@ -5319,7 +5959,8 @@ namespace Api { offset: int; length: int; url: string; - }; + static fromReader(reader: Reader): MessageEntityTextUrl; + } export class MessageEntityMentionName extends VirtualClass<{ offset: int; length: int; @@ -5328,7 +5969,8 @@ namespace Api { offset: int; length: int; userId: long; - }; + static fromReader(reader: Reader): MessageEntityMentionName; + } export class InputMessageEntityMentionName extends VirtualClass<{ offset: int; length: int; @@ -5337,49 +5979,56 @@ namespace Api { offset: int; length: int; userId: Api.TypeInputUser; - }; + static fromReader(reader: Reader): InputMessageEntityMentionName; + } export class MessageEntityPhone extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntityPhone; + } export class MessageEntityCashtag extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntityCashtag; + } export class MessageEntityUnderline extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntityUnderline; + } export class MessageEntityStrike extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntityStrike; + } export class MessageEntityBankCard extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntityBankCard; + } export class MessageEntitySpoiler extends VirtualClass<{ offset: int; length: int; }> { offset: int; length: int; - }; + static fromReader(reader: Reader): MessageEntitySpoiler; + } export class MessageEntityCustomEmoji extends VirtualClass<{ offset: int; length: int; @@ -5388,26 +6037,31 @@ namespace Api { offset: int; length: int; documentId: long; - }; + static fromReader(reader: Reader): MessageEntityCustomEmoji; + } export class MessageEntityBlockquote extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; collapsed?: true; offset: int; length: int; }> { - // flags: undefined; + // flags: Api.Type; collapsed?: true; offset: int; length: int; - }; - export class InputChannelEmpty extends VirtualClass {}; + static fromReader(reader: Reader): MessageEntityBlockquote; + } + export class InputChannelEmpty extends VirtualClass { + static fromReader(reader: Reader): InputChannelEmpty; + } export class InputChannel extends VirtualClass<{ channelId: long; accessHash: long; }> { channelId: long; accessHash: long; - }; + static fromReader(reader: Reader): InputChannel; + } export class InputChannelFromMessage extends VirtualClass<{ peer: Api.TypeInputPeer; msgId: int; @@ -5416,63 +6070,71 @@ namespace Api { peer: Api.TypeInputPeer; msgId: int; channelId: long; - }; + static fromReader(reader: Reader): InputChannelFromMessage; + } export class MessageRange extends VirtualClass<{ minId: int; maxId: int; }> { minId: int; maxId: int; - }; - export class ChannelMessagesFilterEmpty extends VirtualClass {}; + static fromReader(reader: Reader): MessageRange; + } + export class ChannelMessagesFilterEmpty extends VirtualClass { + static fromReader(reader: Reader): ChannelMessagesFilterEmpty; + } export class ChannelMessagesFilter extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; excludeNewMessages?: true; ranges: Api.TypeMessageRange[]; }> { - // flags: undefined; + // flags: Api.Type; excludeNewMessages?: true; ranges: Api.TypeMessageRange[]; - }; + static fromReader(reader: Reader): ChannelMessagesFilter; + } export class ChannelParticipant extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; userId: long; date: int; subscriptionUntilDate?: int; }> { - // flags: undefined; + // flags: Api.Type; userId: long; date: int; subscriptionUntilDate?: int; - }; + static fromReader(reader: Reader): ChannelParticipant; + } export class ChannelParticipantSelf extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; viaRequest?: true; userId: long; inviterId: long; date: int; subscriptionUntilDate?: int; }> { - // flags: undefined; + // flags: Api.Type; viaRequest?: true; userId: long; inviterId: long; date: int; subscriptionUntilDate?: int; - }; + static fromReader(reader: Reader): ChannelParticipantSelf; + } export class ChannelParticipantCreator extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; userId: long; adminRights: Api.TypeChatAdminRights; rank?: string; }> { - // flags: undefined; + // flags: Api.Type; userId: long; adminRights: Api.TypeChatAdminRights; rank?: string; - }; + static fromReader(reader: Reader): ChannelParticipantCreator; + } export class ChannelParticipantAdmin extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; canEdit?: true; self?: true; userId: long; @@ -5482,7 +6144,7 @@ namespace Api { adminRights: Api.TypeChatAdminRights; rank?: string; }> { - // flags: undefined; + // flags: Api.Type; canEdit?: true; self?: true; userId: long; @@ -5491,104 +6153,121 @@ namespace Api { date: int; adminRights: Api.TypeChatAdminRights; rank?: string; - }; + static fromReader(reader: Reader): ChannelParticipantAdmin; + } export class ChannelParticipantBanned extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; left?: true; peer: Api.TypePeer; kickedBy: long; date: int; bannedRights: Api.TypeChatBannedRights; }> { - // flags: undefined; + // flags: Api.Type; left?: true; peer: Api.TypePeer; kickedBy: long; date: int; bannedRights: Api.TypeChatBannedRights; - }; + static fromReader(reader: Reader): ChannelParticipantBanned; + } export class ChannelParticipantLeft extends VirtualClass<{ peer: Api.TypePeer; }> { peer: Api.TypePeer; - }; - export class ChannelParticipantsRecent extends VirtualClass {}; - export class ChannelParticipantsAdmins extends VirtualClass {}; + static fromReader(reader: Reader): ChannelParticipantLeft; + } + export class ChannelParticipantsRecent extends VirtualClass { + static fromReader(reader: Reader): ChannelParticipantsRecent; + } + export class ChannelParticipantsAdmins extends VirtualClass { + static fromReader(reader: Reader): ChannelParticipantsAdmins; + } export class ChannelParticipantsKicked extends VirtualClass<{ q: string; }> { q: string; - }; - export class ChannelParticipantsBots extends VirtualClass {}; + static fromReader(reader: Reader): ChannelParticipantsKicked; + } + export class ChannelParticipantsBots extends VirtualClass { + static fromReader(reader: Reader): ChannelParticipantsBots; + } export class ChannelParticipantsBanned extends VirtualClass<{ q: string; }> { q: string; - }; + static fromReader(reader: Reader): ChannelParticipantsBanned; + } export class ChannelParticipantsSearch extends VirtualClass<{ q: string; }> { q: string; - }; + static fromReader(reader: Reader): ChannelParticipantsSearch; + } export class ChannelParticipantsContacts extends VirtualClass<{ q: string; }> { q: string; - }; + static fromReader(reader: Reader): ChannelParticipantsContacts; + } export class ChannelParticipantsMentions extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; q?: string; topMsgId?: int; } | void> { - // flags: undefined; + // flags: Api.Type; q?: string; topMsgId?: int; - }; + static fromReader(reader: Reader): ChannelParticipantsMentions; + } export class InputBotInlineMessageMediaAuto extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; invertMedia?: true; message: string; entities?: Api.TypeMessageEntity[]; replyMarkup?: Api.TypeReplyMarkup; }> { - // flags: undefined; + // flags: Api.Type; invertMedia?: true; message: string; entities?: Api.TypeMessageEntity[]; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): InputBotInlineMessageMediaAuto; + } export class InputBotInlineMessageText extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; noWebpage?: true; invertMedia?: true; message: string; entities?: Api.TypeMessageEntity[]; replyMarkup?: Api.TypeReplyMarkup; }> { - // flags: undefined; + // flags: Api.Type; noWebpage?: true; invertMedia?: true; message: string; entities?: Api.TypeMessageEntity[]; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): InputBotInlineMessageText; + } export class InputBotInlineMessageMediaGeo extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; geoPoint: Api.TypeInputGeoPoint; heading?: int; period?: int; proximityNotificationRadius?: int; replyMarkup?: Api.TypeReplyMarkup; }> { - // flags: undefined; + // flags: Api.Type; geoPoint: Api.TypeInputGeoPoint; heading?: int; period?: int; proximityNotificationRadius?: int; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): InputBotInlineMessageMediaGeo; + } export class InputBotInlineMessageMediaVenue extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; geoPoint: Api.TypeInputGeoPoint; title: string; address: string; @@ -5597,7 +6276,7 @@ namespace Api { venueType: string; replyMarkup?: Api.TypeReplyMarkup; }> { - // flags: undefined; + // flags: Api.Type; geoPoint: Api.TypeInputGeoPoint; title: string; address: string; @@ -5605,31 +6284,34 @@ namespace Api { venueId: string; venueType: string; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): InputBotInlineMessageMediaVenue; + } export class InputBotInlineMessageMediaContact extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; phoneNumber: string; firstName: string; lastName: string; vcard: string; replyMarkup?: Api.TypeReplyMarkup; }> { - // flags: undefined; + // flags: Api.Type; phoneNumber: string; firstName: string; lastName: string; vcard: string; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): InputBotInlineMessageMediaContact; + } export class InputBotInlineMessageGame extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; replyMarkup?: Api.TypeReplyMarkup; } | void> { - // flags: undefined; + // flags: Api.Type; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): InputBotInlineMessageGame; + } export class InputBotInlineMessageMediaInvoice extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; title: string; description: string; photo?: Api.TypeInputWebDocument; @@ -5639,7 +6321,7 @@ namespace Api { providerData: Api.TypeDataJSON; replyMarkup?: Api.TypeReplyMarkup; }> { - // flags: undefined; + // flags: Api.Type; title: string; description: string; photo?: Api.TypeInputWebDocument; @@ -5648,9 +6330,10 @@ namespace Api { provider: string; providerData: Api.TypeDataJSON; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): InputBotInlineMessageMediaInvoice; + } export class InputBotInlineMessageMediaWebPage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; invertMedia?: true; forceLargeMedia?: true; forceSmallMedia?: true; @@ -5660,7 +6343,7 @@ namespace Api { url: string; replyMarkup?: Api.TypeReplyMarkup; }> { - // flags: undefined; + // flags: Api.Type; invertMedia?: true; forceLargeMedia?: true; forceSmallMedia?: true; @@ -5669,9 +6352,10 @@ namespace Api { entities?: Api.TypeMessageEntity[]; url: string; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): InputBotInlineMessageMediaWebPage; + } export class InputBotInlineResult extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; id: string; type: string; title?: string; @@ -5681,7 +6365,7 @@ namespace Api { content?: Api.TypeInputWebDocument; sendMessage: Api.TypeInputBotInlineMessage; }> { - // flags: undefined; + // flags: Api.Type; id: string; type: string; title?: string; @@ -5690,7 +6374,8 @@ namespace Api { thumb?: Api.TypeInputWebDocument; content?: Api.TypeInputWebDocument; sendMessage: Api.TypeInputBotInlineMessage; - }; + static fromReader(reader: Reader): InputBotInlineResult; + } export class InputBotInlineResultPhoto extends VirtualClass<{ id: string; type: string; @@ -5701,9 +6386,10 @@ namespace Api { type: string; photo: Api.TypeInputPhoto; sendMessage: Api.TypeInputBotInlineMessage; - }; + static fromReader(reader: Reader): InputBotInlineResultPhoto; + } export class InputBotInlineResultDocument extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; id: string; type: string; title?: string; @@ -5711,14 +6397,15 @@ namespace Api { document: Api.TypeInputDocument; sendMessage: Api.TypeInputBotInlineMessage; }> { - // flags: undefined; + // flags: Api.Type; id: string; type: string; title?: string; description?: string; document: Api.TypeInputDocument; sendMessage: Api.TypeInputBotInlineMessage; - }; + static fromReader(reader: Reader): InputBotInlineResultDocument; + } export class InputBotInlineResultGame extends VirtualClass<{ id: string; shortName: string; @@ -5727,52 +6414,56 @@ namespace Api { id: string; shortName: string; sendMessage: Api.TypeInputBotInlineMessage; - }; + static fromReader(reader: Reader): InputBotInlineResultGame; + } export class BotInlineMessageMediaAuto extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; invertMedia?: true; message: string; entities?: Api.TypeMessageEntity[]; replyMarkup?: Api.TypeReplyMarkup; }> { - // flags: undefined; + // flags: Api.Type; invertMedia?: true; message: string; entities?: Api.TypeMessageEntity[]; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): BotInlineMessageMediaAuto; + } export class BotInlineMessageText extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; noWebpage?: true; invertMedia?: true; message: string; entities?: Api.TypeMessageEntity[]; replyMarkup?: Api.TypeReplyMarkup; }> { - // flags: undefined; + // flags: Api.Type; noWebpage?: true; invertMedia?: true; message: string; entities?: Api.TypeMessageEntity[]; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): BotInlineMessageText; + } export class BotInlineMessageMediaGeo extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; geo: Api.TypeGeoPoint; heading?: int; period?: int; proximityNotificationRadius?: int; replyMarkup?: Api.TypeReplyMarkup; }> { - // flags: undefined; + // flags: Api.Type; geo: Api.TypeGeoPoint; heading?: int; period?: int; proximityNotificationRadius?: int; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): BotInlineMessageMediaGeo; + } export class BotInlineMessageMediaVenue extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; geo: Api.TypeGeoPoint; title: string; address: string; @@ -5781,7 +6472,7 @@ namespace Api { venueType: string; replyMarkup?: Api.TypeReplyMarkup; }> { - // flags: undefined; + // flags: Api.Type; geo: Api.TypeGeoPoint; title: string; address: string; @@ -5789,24 +6480,26 @@ namespace Api { venueId: string; venueType: string; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): BotInlineMessageMediaVenue; + } export class BotInlineMessageMediaContact extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; phoneNumber: string; firstName: string; lastName: string; vcard: string; replyMarkup?: Api.TypeReplyMarkup; }> { - // flags: undefined; + // flags: Api.Type; phoneNumber: string; firstName: string; lastName: string; vcard: string; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): BotInlineMessageMediaContact; + } export class BotInlineMessageMediaInvoice extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; shippingAddressRequested?: true; test?: true; title: string; @@ -5816,7 +6509,7 @@ namespace Api { totalAmount: long; replyMarkup?: Api.TypeReplyMarkup; }> { - // flags: undefined; + // flags: Api.Type; shippingAddressRequested?: true; test?: true; title: string; @@ -5825,9 +6518,10 @@ namespace Api { currency: string; totalAmount: long; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): BotInlineMessageMediaInvoice; + } export class BotInlineMessageMediaWebPage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; invertMedia?: true; forceLargeMedia?: true; forceSmallMedia?: true; @@ -5838,7 +6532,7 @@ namespace Api { url: string; replyMarkup?: Api.TypeReplyMarkup; }> { - // flags: undefined; + // flags: Api.Type; invertMedia?: true; forceLargeMedia?: true; forceSmallMedia?: true; @@ -5848,9 +6542,10 @@ namespace Api { entities?: Api.TypeMessageEntity[]; url: string; replyMarkup?: Api.TypeReplyMarkup; - }; + static fromReader(reader: Reader): BotInlineMessageMediaWebPage; + } export class BotInlineResult extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; id: string; type: string; title?: string; @@ -5860,7 +6555,7 @@ namespace Api { content?: Api.TypeWebDocument; sendMessage: Api.TypeBotInlineMessage; }> { - // flags: undefined; + // flags: Api.Type; id: string; type: string; title?: string; @@ -5869,9 +6564,10 @@ namespace Api { thumb?: Api.TypeWebDocument; content?: Api.TypeWebDocument; sendMessage: Api.TypeBotInlineMessage; - }; + static fromReader(reader: Reader): BotInlineResult; + } export class BotInlineMediaResult extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; id: string; type: string; photo?: Api.TypePhoto; @@ -5880,7 +6576,7 @@ namespace Api { description?: string; sendMessage: Api.TypeBotInlineMessage; }> { - // flags: undefined; + // flags: Api.Type; id: string; type: string; photo?: Api.TypePhoto; @@ -5888,16 +6584,18 @@ namespace Api { title?: string; description?: string; sendMessage: Api.TypeBotInlineMessage; - }; + static fromReader(reader: Reader): BotInlineMediaResult; + } export class ExportedMessageLink extends VirtualClass<{ link: string; html: string; }> { link: string; html: string; - }; + static fromReader(reader: Reader): ExportedMessageLink; + } export class MessageFwdHeader extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; imported?: true; savedOut?: true; fromId?: Api.TypePeer; @@ -5912,7 +6610,7 @@ namespace Api { savedDate?: int; psaType?: string; }> { - // flags: undefined; + // flags: Api.Type; imported?: true; savedOut?: true; fromId?: Api.TypePeer; @@ -5926,7 +6624,8 @@ namespace Api { savedFromName?: string; savedDate?: int; psaType?: string; - }; + static fromReader(reader: Reader): MessageFwdHeader; + } export class InputBotInlineMessageID extends VirtualClass<{ dcId: int; id: long; @@ -5935,7 +6634,8 @@ namespace Api { dcId: int; id: long; accessHash: long; - }; + static fromReader(reader: Reader): InputBotInlineMessageID; + } export class InputBotInlineMessageID64 extends VirtualClass<{ dcId: int; ownerId: long; @@ -5946,30 +6646,51 @@ namespace Api { ownerId: long; id: int; accessHash: long; - }; + static fromReader(reader: Reader): InputBotInlineMessageID64; + } export class InlineBotSwitchPM extends VirtualClass<{ text: string; startParam: string; }> { text: string; startParam: string; - }; + static fromReader(reader: Reader): InlineBotSwitchPM; + } export class TopPeer extends VirtualClass<{ peer: Api.TypePeer; rating: double; }> { peer: Api.TypePeer; rating: double; - }; - export class TopPeerCategoryBotsPM extends VirtualClass {}; - export class TopPeerCategoryBotsInline extends VirtualClass {}; - export class TopPeerCategoryCorrespondents extends VirtualClass {}; - export class TopPeerCategoryGroups extends VirtualClass {}; - export class TopPeerCategoryChannels extends VirtualClass {}; - export class TopPeerCategoryPhoneCalls extends VirtualClass {}; - export class TopPeerCategoryForwardUsers extends VirtualClass {}; - export class TopPeerCategoryForwardChats extends VirtualClass {}; - export class TopPeerCategoryBotsApp extends VirtualClass {}; + static fromReader(reader: Reader): TopPeer; + } + export class TopPeerCategoryBotsPM extends VirtualClass { + static fromReader(reader: Reader): TopPeerCategoryBotsPM; + } + export class TopPeerCategoryBotsInline extends VirtualClass { + static fromReader(reader: Reader): TopPeerCategoryBotsInline; + } + export class TopPeerCategoryCorrespondents extends VirtualClass { + static fromReader(reader: Reader): TopPeerCategoryCorrespondents; + } + export class TopPeerCategoryGroups extends VirtualClass { + static fromReader(reader: Reader): TopPeerCategoryGroups; + } + export class TopPeerCategoryChannels extends VirtualClass { + static fromReader(reader: Reader): TopPeerCategoryChannels; + } + export class TopPeerCategoryPhoneCalls extends VirtualClass { + static fromReader(reader: Reader): TopPeerCategoryPhoneCalls; + } + export class TopPeerCategoryForwardUsers extends VirtualClass { + static fromReader(reader: Reader): TopPeerCategoryForwardUsers; + } + export class TopPeerCategoryForwardChats extends VirtualClass { + static fromReader(reader: Reader): TopPeerCategoryForwardChats; + } + export class TopPeerCategoryBotsApp extends VirtualClass { + static fromReader(reader: Reader): TopPeerCategoryBotsApp; + } export class TopPeerCategoryPeers extends VirtualClass<{ category: Api.TypeTopPeerCategory; count: int; @@ -5978,16 +6699,18 @@ namespace Api { category: Api.TypeTopPeerCategory; count: int; peers: Api.TypeTopPeer[]; - }; + static fromReader(reader: Reader): TopPeerCategoryPeers; + } export class DraftMessageEmpty extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; date?: int; } | void> { - // flags: undefined; + // flags: Api.Type; date?: int; - }; + static fromReader(reader: Reader): DraftMessageEmpty; + } export class DraftMessage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; noWebpage?: true; invertMedia?: true; replyTo?: Api.TypeInputReplyTo; @@ -5997,7 +6720,7 @@ namespace Api { date: int; effect?: long; }> { - // flags: undefined; + // flags: Api.Type; noWebpage?: true; invertMedia?: true; replyTo?: Api.TypeInputReplyTo; @@ -6006,21 +6729,24 @@ namespace Api { media?: Api.TypeInputMedia; date: int; effect?: long; - }; + static fromReader(reader: Reader): DraftMessage; + } export class StickerSetCovered extends VirtualClass<{ set: Api.TypeStickerSet; cover: Api.TypeDocument; }> { set: Api.TypeStickerSet; cover: Api.TypeDocument; - }; + static fromReader(reader: Reader): StickerSetCovered; + } export class StickerSetMultiCovered extends VirtualClass<{ set: Api.TypeStickerSet; covers: Api.TypeDocument[]; }> { set: Api.TypeStickerSet; covers: Api.TypeDocument[]; - }; + static fromReader(reader: Reader): StickerSetMultiCovered; + } export class StickerSetFullCovered extends VirtualClass<{ set: Api.TypeStickerSet; packs: Api.TypeStickerPack[]; @@ -6031,12 +6757,14 @@ namespace Api { packs: Api.TypeStickerPack[]; keywords: Api.TypeStickerKeyword[]; documents: Api.TypeDocument[]; - }; + static fromReader(reader: Reader): StickerSetFullCovered; + } export class StickerSetNoCovered extends VirtualClass<{ set: Api.TypeStickerSet; }> { set: Api.TypeStickerSet; - }; + static fromReader(reader: Reader): StickerSetNoCovered; + } export class MaskCoords extends VirtualClass<{ n: int; x: double; @@ -6047,19 +6775,22 @@ namespace Api { x: double; y: double; zoom: double; - }; + static fromReader(reader: Reader): MaskCoords; + } export class InputStickeredMediaPhoto extends VirtualClass<{ id: Api.TypeInputPhoto; }> { id: Api.TypeInputPhoto; - }; + static fromReader(reader: Reader): InputStickeredMediaPhoto; + } export class InputStickeredMediaDocument extends VirtualClass<{ id: Api.TypeInputDocument; }> { id: Api.TypeInputDocument; - }; + static fromReader(reader: Reader): InputStickeredMediaDocument; + } export class Game extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; id: long; accessHash: long; shortName: string; @@ -6068,7 +6799,7 @@ namespace Api { photo: Api.TypePhoto; document?: Api.TypeDocument; }> { - // flags: undefined; + // flags: Api.Type; id: long; accessHash: long; shortName: string; @@ -6076,21 +6807,24 @@ namespace Api { description: string; photo: Api.TypePhoto; document?: Api.TypeDocument; - }; + static fromReader(reader: Reader): Game; + } export class InputGameID extends VirtualClass<{ id: long; accessHash: long; }> { id: long; accessHash: long; - }; + static fromReader(reader: Reader): InputGameID; + } export class InputGameShortName extends VirtualClass<{ botId: Api.TypeInputUser; shortName: string; }> { botId: Api.TypeInputUser; shortName: string; - }; + static fromReader(reader: Reader): InputGameShortName; + } export class HighScore extends VirtualClass<{ pos: int; userId: long; @@ -6099,38 +6833,47 @@ namespace Api { pos: int; userId: long; score: int; - }; - export class TextEmpty extends VirtualClass {}; + static fromReader(reader: Reader): HighScore; + } + export class TextEmpty extends VirtualClass { + static fromReader(reader: Reader): TextEmpty; + } export class TextPlain extends VirtualClass<{ text: string; }> { text: string; - }; + static fromReader(reader: Reader): TextPlain; + } export class TextBold extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): TextBold; + } export class TextItalic extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): TextItalic; + } export class TextUnderline extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): TextUnderline; + } export class TextStrike extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): TextStrike; + } export class TextFixed extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): TextFixed; + } export class TextUrl extends VirtualClass<{ text: Api.TypeRichText; url: string; @@ -6139,41 +6882,48 @@ namespace Api { text: Api.TypeRichText; url: string; webpageId: long; - }; + static fromReader(reader: Reader): TextUrl; + } export class TextEmail extends VirtualClass<{ text: Api.TypeRichText; email: string; }> { text: Api.TypeRichText; email: string; - }; + static fromReader(reader: Reader): TextEmail; + } export class TextConcat extends VirtualClass<{ texts: Api.TypeRichText[]; }> { texts: Api.TypeRichText[]; - }; + static fromReader(reader: Reader): TextConcat; + } export class TextSubscript extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): TextSubscript; + } export class TextSuperscript extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): TextSuperscript; + } export class TextMarked extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): TextMarked; + } export class TextPhone extends VirtualClass<{ text: Api.TypeRichText; phone: string; }> { text: Api.TypeRichText; phone: string; - }; + static fromReader(reader: Reader): TextPhone; + } export class TextImage extends VirtualClass<{ documentId: long; w: int; @@ -6182,117 +6932,138 @@ namespace Api { documentId: long; w: int; h: int; - }; + static fromReader(reader: Reader): TextImage; + } export class TextAnchor extends VirtualClass<{ text: Api.TypeRichText; name: string; }> { text: Api.TypeRichText; name: string; - }; - export class PageBlockUnsupported extends VirtualClass {}; + static fromReader(reader: Reader): TextAnchor; + } + export class PageBlockUnsupported extends VirtualClass { + static fromReader(reader: Reader): PageBlockUnsupported; + } export class PageBlockTitle extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): PageBlockTitle; + } export class PageBlockSubtitle extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): PageBlockSubtitle; + } export class PageBlockAuthorDate extends VirtualClass<{ author: Api.TypeRichText; publishedDate: int; }> { author: Api.TypeRichText; publishedDate: int; - }; + static fromReader(reader: Reader): PageBlockAuthorDate; + } export class PageBlockHeader extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): PageBlockHeader; + } export class PageBlockSubheader extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): PageBlockSubheader; + } export class PageBlockParagraph extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): PageBlockParagraph; + } export class PageBlockPreformatted extends VirtualClass<{ text: Api.TypeRichText; language: string; }> { text: Api.TypeRichText; language: string; - }; + static fromReader(reader: Reader): PageBlockPreformatted; + } export class PageBlockFooter extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; - export class PageBlockDivider extends VirtualClass {}; + static fromReader(reader: Reader): PageBlockFooter; + } + export class PageBlockDivider extends VirtualClass { + static fromReader(reader: Reader): PageBlockDivider; + } export class PageBlockAnchor extends VirtualClass<{ name: string; }> { name: string; - }; + static fromReader(reader: Reader): PageBlockAnchor; + } export class PageBlockList extends VirtualClass<{ items: Api.TypePageListItem[]; }> { items: Api.TypePageListItem[]; - }; + static fromReader(reader: Reader): PageBlockList; + } export class PageBlockBlockquote extends VirtualClass<{ text: Api.TypeRichText; caption: Api.TypeRichText; }> { text: Api.TypeRichText; caption: Api.TypeRichText; - }; + static fromReader(reader: Reader): PageBlockBlockquote; + } export class PageBlockPullquote extends VirtualClass<{ text: Api.TypeRichText; caption: Api.TypeRichText; }> { text: Api.TypeRichText; caption: Api.TypeRichText; - }; + static fromReader(reader: Reader): PageBlockPullquote; + } export class PageBlockPhoto extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; photoId: long; caption: Api.TypePageCaption; url?: string; webpageId?: long; }> { - // flags: undefined; + // flags: Api.Type; photoId: long; caption: Api.TypePageCaption; url?: string; webpageId?: long; - }; + static fromReader(reader: Reader): PageBlockPhoto; + } export class PageBlockVideo extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; autoplay?: true; loop?: true; videoId: long; caption: Api.TypePageCaption; }> { - // flags: undefined; + // flags: Api.Type; autoplay?: true; loop?: true; videoId: long; caption: Api.TypePageCaption; - }; + static fromReader(reader: Reader): PageBlockVideo; + } export class PageBlockCover extends VirtualClass<{ cover: Api.TypePageBlock; }> { cover: Api.TypePageBlock; - }; + static fromReader(reader: Reader): PageBlockCover; + } export class PageBlockEmbed extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; fullWidth?: true; allowScrolling?: true; url?: string; @@ -6302,7 +7073,7 @@ namespace Api { h?: int; caption: Api.TypePageCaption; }> { - // flags: undefined; + // flags: Api.Type; fullWidth?: true; allowScrolling?: true; url?: string; @@ -6311,7 +7082,8 @@ namespace Api { w?: int; h?: int; caption: Api.TypePageCaption; - }; + static fromReader(reader: Reader): PageBlockEmbed; + } export class PageBlockEmbedPost extends VirtualClass<{ url: string; webpageId: long; @@ -6328,74 +7100,84 @@ namespace Api { date: int; blocks: Api.TypePageBlock[]; caption: Api.TypePageCaption; - }; + static fromReader(reader: Reader): PageBlockEmbedPost; + } export class PageBlockCollage extends VirtualClass<{ items: Api.TypePageBlock[]; caption: Api.TypePageCaption; }> { items: Api.TypePageBlock[]; caption: Api.TypePageCaption; - }; + static fromReader(reader: Reader): PageBlockCollage; + } export class PageBlockSlideshow extends VirtualClass<{ items: Api.TypePageBlock[]; caption: Api.TypePageCaption; }> { items: Api.TypePageBlock[]; caption: Api.TypePageCaption; - }; + static fromReader(reader: Reader): PageBlockSlideshow; + } export class PageBlockChannel extends VirtualClass<{ channel: Api.TypeChat; }> { channel: Api.TypeChat; - }; + static fromReader(reader: Reader): PageBlockChannel; + } export class PageBlockAudio extends VirtualClass<{ audioId: long; caption: Api.TypePageCaption; }> { audioId: long; caption: Api.TypePageCaption; - }; + static fromReader(reader: Reader): PageBlockAudio; + } export class PageBlockKicker extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): PageBlockKicker; + } export class PageBlockTable extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; bordered?: true; striped?: true; title: Api.TypeRichText; rows: Api.TypePageTableRow[]; }> { - // flags: undefined; + // flags: Api.Type; bordered?: true; striped?: true; title: Api.TypeRichText; rows: Api.TypePageTableRow[]; - }; + static fromReader(reader: Reader): PageBlockTable; + } export class PageBlockOrderedList extends VirtualClass<{ items: Api.TypePageListOrderedItem[]; }> { items: Api.TypePageListOrderedItem[]; - }; + static fromReader(reader: Reader): PageBlockOrderedList; + } export class PageBlockDetails extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; open?: true; blocks: Api.TypePageBlock[]; title: Api.TypeRichText; }> { - // flags: undefined; + // flags: Api.Type; open?: true; blocks: Api.TypePageBlock[]; title: Api.TypeRichText; - }; + static fromReader(reader: Reader): PageBlockDetails; + } export class PageBlockRelatedArticles extends VirtualClass<{ title: Api.TypeRichText; articles: Api.TypePageRelatedArticle[]; }> { title: Api.TypeRichText; articles: Api.TypePageRelatedArticle[]; - }; + static fromReader(reader: Reader): PageBlockRelatedArticles; + } export class PageBlockMap extends VirtualClass<{ geo: Api.TypeGeoPoint; zoom: int; @@ -6408,30 +7190,42 @@ namespace Api { w: int; h: int; caption: Api.TypePageCaption; - }; - export class PhoneCallDiscardReasonMissed extends VirtualClass {}; - export class PhoneCallDiscardReasonDisconnect extends VirtualClass {}; - export class PhoneCallDiscardReasonHangup extends VirtualClass {}; - export class PhoneCallDiscardReasonBusy extends VirtualClass {}; + static fromReader(reader: Reader): PageBlockMap; + } + export class PhoneCallDiscardReasonMissed extends VirtualClass { + static fromReader(reader: Reader): PhoneCallDiscardReasonMissed; + } + export class PhoneCallDiscardReasonDisconnect extends VirtualClass { + static fromReader(reader: Reader): PhoneCallDiscardReasonDisconnect; + } + export class PhoneCallDiscardReasonHangup extends VirtualClass { + static fromReader(reader: Reader): PhoneCallDiscardReasonHangup; + } + export class PhoneCallDiscardReasonBusy extends VirtualClass { + static fromReader(reader: Reader): PhoneCallDiscardReasonBusy; + } export class PhoneCallDiscardReasonAllowGroupCall extends VirtualClass<{ encryptedKey: bytes; }> { encryptedKey: bytes; - }; + static fromReader(reader: Reader): PhoneCallDiscardReasonAllowGroupCall; + } export class DataJSON extends VirtualClass<{ data: string; }> { data: string; - }; + static fromReader(reader: Reader): DataJSON; + } export class LabeledPrice extends VirtualClass<{ label: string; amount: long; }> { label: string; amount: long; - }; + static fromReader(reader: Reader): LabeledPrice; + } export class Invoice extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; test?: true; nameRequested?: true; phoneRequested?: true; @@ -6448,7 +7242,7 @@ namespace Api { termsUrl?: string; subscriptionPeriod?: int; }> { - // flags: undefined; + // flags: Api.Type; test?: true; nameRequested?: true; phoneRequested?: true; @@ -6464,14 +7258,16 @@ namespace Api { suggestedTipAmounts?: long[]; termsUrl?: string; subscriptionPeriod?: int; - }; + static fromReader(reader: Reader): Invoice; + } export class PaymentCharge extends VirtualClass<{ id: string; providerChargeId: string; }> { id: string; providerChargeId: string; - }; + static fromReader(reader: Reader): PaymentCharge; + } export class PostAddress extends VirtualClass<{ streetLine1: string; streetLine2: string; @@ -6486,27 +7282,30 @@ namespace Api { state: string; countryIso2: string; postCode: string; - }; + static fromReader(reader: Reader): PostAddress; + } export class PaymentRequestedInfo extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; name?: string; phone?: string; email?: string; shippingAddress?: Api.TypePostAddress; } | void> { - // flags: undefined; + // flags: Api.Type; name?: string; phone?: string; email?: string; shippingAddress?: Api.TypePostAddress; - }; + static fromReader(reader: Reader): PaymentRequestedInfo; + } export class PaymentSavedCredentialsCard extends VirtualClass<{ id: string; title: string; }> { id: string; title: string; - }; + static fromReader(reader: Reader): PaymentSavedCredentialsCard; + } export class WebDocument extends VirtualClass<{ url: string; accessHash: long; @@ -6519,7 +7318,8 @@ namespace Api { size: int; mimeType: string; attributes: Api.TypeDocumentAttribute[]; - }; + static fromReader(reader: Reader): WebDocument; + } export class WebDocumentNoProxy extends VirtualClass<{ url: string; size: int; @@ -6530,7 +7330,8 @@ namespace Api { size: int; mimeType: string; attributes: Api.TypeDocumentAttribute[]; - }; + static fromReader(reader: Reader): WebDocumentNoProxy; + } export class InputWebDocument extends VirtualClass<{ url: string; size: int; @@ -6541,14 +7342,16 @@ namespace Api { size: int; mimeType: string; attributes: Api.TypeDocumentAttribute[]; - }; + static fromReader(reader: Reader): InputWebDocument; + } export class InputWebFileLocation extends VirtualClass<{ url: string; accessHash: long; }> { url: string; accessHash: long; - }; + static fromReader(reader: Reader): InputWebFileLocation; + } export class InputWebFileGeoPointLocation extends VirtualClass<{ geoPoint: Api.TypeInputGeoPoint; accessHash: long; @@ -6563,46 +7366,52 @@ namespace Api { h: int; zoom: int; scale: int; - }; + static fromReader(reader: Reader): InputWebFileGeoPointLocation; + } export class InputWebFileAudioAlbumThumbLocation extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; small?: true; document?: Api.TypeInputDocument; title?: string; performer?: string; } | void> { - // flags: undefined; + // flags: Api.Type; small?: true; document?: Api.TypeInputDocument; title?: string; performer?: string; - }; + static fromReader(reader: Reader): InputWebFileAudioAlbumThumbLocation; + } export class InputPaymentCredentialsSaved extends VirtualClass<{ id: string; tmpPassword: bytes; }> { id: string; tmpPassword: bytes; - }; + static fromReader(reader: Reader): InputPaymentCredentialsSaved; + } export class InputPaymentCredentials extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; save?: true; data: Api.TypeDataJSON; }> { - // flags: undefined; + // flags: Api.Type; save?: true; data: Api.TypeDataJSON; - }; + static fromReader(reader: Reader): InputPaymentCredentials; + } export class InputPaymentCredentialsApplePay extends VirtualClass<{ paymentData: Api.TypeDataJSON; }> { paymentData: Api.TypeDataJSON; - }; + static fromReader(reader: Reader): InputPaymentCredentialsApplePay; + } export class InputPaymentCredentialsGooglePay extends VirtualClass<{ paymentToken: Api.TypeDataJSON; }> { paymentToken: Api.TypeDataJSON; - }; + static fromReader(reader: Reader): InputPaymentCredentialsGooglePay; + } export class ShippingOption extends VirtualClass<{ id: string; title: string; @@ -6611,34 +7420,38 @@ namespace Api { id: string; title: string; prices: Api.TypeLabeledPrice[]; - }; + static fromReader(reader: Reader): ShippingOption; + } export class InputStickerSetItem extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; document: Api.TypeInputDocument; emoji: string; maskCoords?: Api.TypeMaskCoords; keywords?: string; }> { - // flags: undefined; + // flags: Api.Type; document: Api.TypeInputDocument; emoji: string; maskCoords?: Api.TypeMaskCoords; keywords?: string; - }; + static fromReader(reader: Reader): InputStickerSetItem; + } export class InputPhoneCall extends VirtualClass<{ id: long; accessHash: long; }> { id: long; accessHash: long; - }; + static fromReader(reader: Reader): InputPhoneCall; + } export class PhoneCallEmpty extends VirtualClass<{ id: long; }> { id: long; - }; + static fromReader(reader: Reader): PhoneCallEmpty; + } export class PhoneCallWaiting extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; video?: true; id: long; accessHash: long; @@ -6649,7 +7462,7 @@ namespace Api { receiveDate?: int; conferenceCall?: Api.TypeInputGroupCall; }> { - // flags: undefined; + // flags: Api.Type; video?: true; id: long; accessHash: long; @@ -6659,9 +7472,10 @@ namespace Api { protocol: Api.TypePhoneCallProtocol; receiveDate?: int; conferenceCall?: Api.TypeInputGroupCall; - }; + static fromReader(reader: Reader): PhoneCallWaiting; + } export class PhoneCallRequested extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; video?: true; id: long; accessHash: long; @@ -6672,7 +7486,7 @@ namespace Api { protocol: Api.TypePhoneCallProtocol; conferenceCall?: Api.TypeInputGroupCall; }> { - // flags: undefined; + // flags: Api.Type; video?: true; id: long; accessHash: long; @@ -6682,9 +7496,10 @@ namespace Api { gAHash: bytes; protocol: Api.TypePhoneCallProtocol; conferenceCall?: Api.TypeInputGroupCall; - }; + static fromReader(reader: Reader): PhoneCallRequested; + } export class PhoneCallAccepted extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; video?: true; id: long; accessHash: long; @@ -6695,7 +7510,7 @@ namespace Api { protocol: Api.TypePhoneCallProtocol; conferenceCall?: Api.TypeInputGroupCall; }> { - // flags: undefined; + // flags: Api.Type; video?: true; id: long; accessHash: long; @@ -6705,9 +7520,10 @@ namespace Api { gB: bytes; protocol: Api.TypePhoneCallProtocol; conferenceCall?: Api.TypeInputGroupCall; - }; + static fromReader(reader: Reader): PhoneCallAccepted; + } export class PhoneCall extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; p2pAllowed?: true; video?: true; id: long; @@ -6723,7 +7539,7 @@ namespace Api { customParameters?: Api.TypeDataJSON; conferenceCall?: Api.TypeInputGroupCall; }> { - // flags: undefined; + // flags: Api.Type; p2pAllowed?: true; video?: true; id: long; @@ -6738,9 +7554,10 @@ namespace Api { startDate: int; customParameters?: Api.TypeDataJSON; conferenceCall?: Api.TypeInputGroupCall; - }; + static fromReader(reader: Reader): PhoneCall; + } export class PhoneCallDiscarded extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; needRating?: true; needDebug?: true; video?: true; @@ -6749,7 +7566,7 @@ namespace Api { duration?: int; conferenceCall?: Api.TypeInputGroupCall; }> { - // flags: undefined; + // flags: Api.Type; needRating?: true; needDebug?: true; video?: true; @@ -6757,9 +7574,10 @@ namespace Api { reason?: Api.TypePhoneCallDiscardReason; duration?: int; conferenceCall?: Api.TypeInputGroupCall; - }; + static fromReader(reader: Reader): PhoneCallDiscarded; + } export class PhoneConnection extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; tcp?: true; id: long; ip: string; @@ -6767,16 +7585,17 @@ namespace Api { port: int; peerTag: bytes; }> { - // flags: undefined; + // flags: Api.Type; tcp?: true; id: long; ip: string; ipv6: string; port: int; peerTag: bytes; - }; + static fromReader(reader: Reader): PhoneConnection; + } export class PhoneConnectionWebrtc extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; turn?: true; stun?: true; id: long; @@ -6786,7 +7605,7 @@ namespace Api { username: string; password: string; }> { - // flags: undefined; + // flags: Api.Type; turn?: true; stun?: true; id: long; @@ -6795,43 +7614,48 @@ namespace Api { port: int; username: string; password: string; - }; + static fromReader(reader: Reader): PhoneConnectionWebrtc; + } export class PhoneCallProtocol extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; udpP2p?: true; udpReflector?: true; minLayer: int; maxLayer: int; libraryVersions: string[]; }> { - // flags: undefined; + // flags: Api.Type; udpP2p?: true; udpReflector?: true; minLayer: int; maxLayer: int; libraryVersions: string[]; - }; + static fromReader(reader: Reader): PhoneCallProtocol; + } export class CdnPublicKey extends VirtualClass<{ dcId: int; publicKey: string; }> { dcId: int; publicKey: string; - }; + static fromReader(reader: Reader): CdnPublicKey; + } export class CdnConfig extends VirtualClass<{ publicKeys: Api.TypeCdnPublicKey[]; }> { publicKeys: Api.TypeCdnPublicKey[]; - }; + static fromReader(reader: Reader): CdnConfig; + } export class LangPackString extends VirtualClass<{ key: string; value: string; }> { key: string; value: string; - }; + static fromReader(reader: Reader): LangPackString; + } export class LangPackStringPluralized extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; key: string; zeroValue?: string; oneValue?: string; @@ -6840,7 +7664,7 @@ namespace Api { manyValue?: string; otherValue: string; }> { - // flags: undefined; + // flags: Api.Type; key: string; zeroValue?: string; oneValue?: string; @@ -6848,12 +7672,14 @@ namespace Api { fewValue?: string; manyValue?: string; otherValue: string; - }; + static fromReader(reader: Reader): LangPackStringPluralized; + } export class LangPackStringDeleted extends VirtualClass<{ key: string; }> { key: string; - }; + static fromReader(reader: Reader): LangPackStringDeleted; + } export class LangPackDifference extends VirtualClass<{ langCode: string; fromVersion: int; @@ -6864,9 +7690,10 @@ namespace Api { fromVersion: int; version: int; strings: Api.TypeLangPackString[]; - }; + static fromReader(reader: Reader): LangPackDifference; + } export class LangPackLanguage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; official?: true; rtl?: true; beta?: true; @@ -6879,7 +7706,7 @@ namespace Api { translatedCount: int; translationsUrl: string; }> { - // flags: undefined; + // flags: Api.Type; official?: true; rtl?: true; beta?: true; @@ -6891,305 +7718,358 @@ namespace Api { stringsCount: int; translatedCount: int; translationsUrl: string; - }; + static fromReader(reader: Reader): LangPackLanguage; + } export class ChannelAdminLogEventActionChangeTitle extends VirtualClass<{ prevValue: string; newValue: string; }> { prevValue: string; newValue: string; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangeTitle; + } export class ChannelAdminLogEventActionChangeAbout extends VirtualClass<{ prevValue: string; newValue: string; }> { prevValue: string; newValue: string; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangeAbout; + } export class ChannelAdminLogEventActionChangeUsername extends VirtualClass<{ prevValue: string; newValue: string; }> { prevValue: string; newValue: string; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangeUsername; + } export class ChannelAdminLogEventActionChangePhoto extends VirtualClass<{ prevPhoto: Api.TypePhoto; newPhoto: Api.TypePhoto; }> { prevPhoto: Api.TypePhoto; newPhoto: Api.TypePhoto; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangePhoto; + } export class ChannelAdminLogEventActionToggleInvites extends VirtualClass<{ newValue: Bool; }> { newValue: Bool; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionToggleInvites; + } export class ChannelAdminLogEventActionToggleSignatures extends VirtualClass<{ newValue: Bool; }> { newValue: Bool; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionToggleSignatures; + } export class ChannelAdminLogEventActionUpdatePinned extends VirtualClass<{ message: Api.TypeMessage; }> { message: Api.TypeMessage; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionUpdatePinned; + } export class ChannelAdminLogEventActionEditMessage extends VirtualClass<{ prevMessage: Api.TypeMessage; newMessage: Api.TypeMessage; }> { prevMessage: Api.TypeMessage; newMessage: Api.TypeMessage; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionEditMessage; + } export class ChannelAdminLogEventActionDeleteMessage extends VirtualClass<{ message: Api.TypeMessage; }> { message: Api.TypeMessage; - }; - export class ChannelAdminLogEventActionParticipantJoin extends VirtualClass {}; - export class ChannelAdminLogEventActionParticipantLeave extends VirtualClass {}; + static fromReader(reader: Reader): ChannelAdminLogEventActionDeleteMessage; + } + export class ChannelAdminLogEventActionParticipantJoin extends VirtualClass { + static fromReader(reader: Reader): ChannelAdminLogEventActionParticipantJoin; + } + export class ChannelAdminLogEventActionParticipantLeave extends VirtualClass { + static fromReader(reader: Reader): ChannelAdminLogEventActionParticipantLeave; + } export class ChannelAdminLogEventActionParticipantInvite extends VirtualClass<{ participant: Api.TypeChannelParticipant; }> { participant: Api.TypeChannelParticipant; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionParticipantInvite; + } export class ChannelAdminLogEventActionParticipantToggleBan extends VirtualClass<{ prevParticipant: Api.TypeChannelParticipant; newParticipant: Api.TypeChannelParticipant; }> { prevParticipant: Api.TypeChannelParticipant; newParticipant: Api.TypeChannelParticipant; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionParticipantToggleBan; + } export class ChannelAdminLogEventActionParticipantToggleAdmin extends VirtualClass<{ prevParticipant: Api.TypeChannelParticipant; newParticipant: Api.TypeChannelParticipant; }> { prevParticipant: Api.TypeChannelParticipant; newParticipant: Api.TypeChannelParticipant; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionParticipantToggleAdmin; + } export class ChannelAdminLogEventActionChangeStickerSet extends VirtualClass<{ prevStickerset: Api.TypeInputStickerSet; newStickerset: Api.TypeInputStickerSet; }> { prevStickerset: Api.TypeInputStickerSet; newStickerset: Api.TypeInputStickerSet; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangeStickerSet; + } export class ChannelAdminLogEventActionTogglePreHistoryHidden extends VirtualClass<{ newValue: Bool; }> { newValue: Bool; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionTogglePreHistoryHidden; + } export class ChannelAdminLogEventActionDefaultBannedRights extends VirtualClass<{ prevBannedRights: Api.TypeChatBannedRights; newBannedRights: Api.TypeChatBannedRights; }> { prevBannedRights: Api.TypeChatBannedRights; newBannedRights: Api.TypeChatBannedRights; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionDefaultBannedRights; + } export class ChannelAdminLogEventActionStopPoll extends VirtualClass<{ message: Api.TypeMessage; }> { message: Api.TypeMessage; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionStopPoll; + } export class ChannelAdminLogEventActionChangeLinkedChat extends VirtualClass<{ prevValue: long; newValue: long; }> { prevValue: long; newValue: long; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangeLinkedChat; + } export class ChannelAdminLogEventActionChangeLocation extends VirtualClass<{ prevValue: Api.TypeChannelLocation; newValue: Api.TypeChannelLocation; }> { prevValue: Api.TypeChannelLocation; newValue: Api.TypeChannelLocation; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangeLocation; + } export class ChannelAdminLogEventActionToggleSlowMode extends VirtualClass<{ prevValue: int; newValue: int; }> { prevValue: int; newValue: int; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionToggleSlowMode; + } export class ChannelAdminLogEventActionStartGroupCall extends VirtualClass<{ call: Api.TypeInputGroupCall; }> { call: Api.TypeInputGroupCall; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionStartGroupCall; + } export class ChannelAdminLogEventActionDiscardGroupCall extends VirtualClass<{ call: Api.TypeInputGroupCall; }> { call: Api.TypeInputGroupCall; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionDiscardGroupCall; + } export class ChannelAdminLogEventActionParticipantMute extends VirtualClass<{ participant: Api.TypeGroupCallParticipant; }> { participant: Api.TypeGroupCallParticipant; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionParticipantMute; + } export class ChannelAdminLogEventActionParticipantUnmute extends VirtualClass<{ participant: Api.TypeGroupCallParticipant; }> { participant: Api.TypeGroupCallParticipant; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionParticipantUnmute; + } export class ChannelAdminLogEventActionToggleGroupCallSetting extends VirtualClass<{ joinMuted: Bool; }> { joinMuted: Bool; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionToggleGroupCallSetting; + } export class ChannelAdminLogEventActionParticipantJoinByInvite extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; viaChatlist?: true; invite: Api.TypeExportedChatInvite; }> { - // flags: undefined; + // flags: Api.Type; viaChatlist?: true; invite: Api.TypeExportedChatInvite; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionParticipantJoinByInvite; + } export class ChannelAdminLogEventActionExportedInviteDelete extends VirtualClass<{ invite: Api.TypeExportedChatInvite; }> { invite: Api.TypeExportedChatInvite; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionExportedInviteDelete; + } export class ChannelAdminLogEventActionExportedInviteRevoke extends VirtualClass<{ invite: Api.TypeExportedChatInvite; }> { invite: Api.TypeExportedChatInvite; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionExportedInviteRevoke; + } export class ChannelAdminLogEventActionExportedInviteEdit extends VirtualClass<{ prevInvite: Api.TypeExportedChatInvite; newInvite: Api.TypeExportedChatInvite; }> { prevInvite: Api.TypeExportedChatInvite; newInvite: Api.TypeExportedChatInvite; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionExportedInviteEdit; + } export class ChannelAdminLogEventActionParticipantVolume extends VirtualClass<{ participant: Api.TypeGroupCallParticipant; }> { participant: Api.TypeGroupCallParticipant; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionParticipantVolume; + } export class ChannelAdminLogEventActionChangeHistoryTTL extends VirtualClass<{ prevValue: int; newValue: int; }> { prevValue: int; newValue: int; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangeHistoryTTL; + } export class ChannelAdminLogEventActionParticipantJoinByRequest extends VirtualClass<{ invite: Api.TypeExportedChatInvite; approvedBy: long; }> { invite: Api.TypeExportedChatInvite; approvedBy: long; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionParticipantJoinByRequest; + } export class ChannelAdminLogEventActionToggleNoForwards extends VirtualClass<{ newValue: Bool; }> { newValue: Bool; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionToggleNoForwards; + } export class ChannelAdminLogEventActionSendMessage extends VirtualClass<{ message: Api.TypeMessage; }> { message: Api.TypeMessage; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionSendMessage; + } export class ChannelAdminLogEventActionChangeAvailableReactions extends VirtualClass<{ prevValue: Api.TypeChatReactions; newValue: Api.TypeChatReactions; }> { prevValue: Api.TypeChatReactions; newValue: Api.TypeChatReactions; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangeAvailableReactions; + } export class ChannelAdminLogEventActionChangeUsernames extends VirtualClass<{ prevValue: string[]; newValue: string[]; }> { prevValue: string[]; newValue: string[]; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangeUsernames; + } export class ChannelAdminLogEventActionToggleForum extends VirtualClass<{ newValue: Bool; }> { newValue: Bool; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionToggleForum; + } export class ChannelAdminLogEventActionCreateTopic extends VirtualClass<{ topic: Api.TypeForumTopic; }> { topic: Api.TypeForumTopic; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionCreateTopic; + } export class ChannelAdminLogEventActionEditTopic extends VirtualClass<{ prevTopic: Api.TypeForumTopic; newTopic: Api.TypeForumTopic; }> { prevTopic: Api.TypeForumTopic; newTopic: Api.TypeForumTopic; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionEditTopic; + } export class ChannelAdminLogEventActionDeleteTopic extends VirtualClass<{ topic: Api.TypeForumTopic; }> { topic: Api.TypeForumTopic; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionDeleteTopic; + } export class ChannelAdminLogEventActionPinTopic extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; prevTopic?: Api.TypeForumTopic; newTopic?: Api.TypeForumTopic; } | void> { - // flags: undefined; + // flags: Api.Type; prevTopic?: Api.TypeForumTopic; newTopic?: Api.TypeForumTopic; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionPinTopic; + } export class ChannelAdminLogEventActionToggleAntiSpam extends VirtualClass<{ newValue: Bool; }> { newValue: Bool; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionToggleAntiSpam; + } export class ChannelAdminLogEventActionChangePeerColor extends VirtualClass<{ prevValue: Api.TypePeerColor; newValue: Api.TypePeerColor; }> { prevValue: Api.TypePeerColor; newValue: Api.TypePeerColor; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangePeerColor; + } export class ChannelAdminLogEventActionChangeProfilePeerColor extends VirtualClass<{ prevValue: Api.TypePeerColor; newValue: Api.TypePeerColor; }> { prevValue: Api.TypePeerColor; newValue: Api.TypePeerColor; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangeProfilePeerColor; + } export class ChannelAdminLogEventActionChangeWallpaper extends VirtualClass<{ prevValue: Api.TypeWallPaper; newValue: Api.TypeWallPaper; }> { prevValue: Api.TypeWallPaper; newValue: Api.TypeWallPaper; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangeWallpaper; + } export class ChannelAdminLogEventActionChangeEmojiStatus extends VirtualClass<{ prevValue: Api.TypeEmojiStatus; newValue: Api.TypeEmojiStatus; }> { prevValue: Api.TypeEmojiStatus; newValue: Api.TypeEmojiStatus; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangeEmojiStatus; + } export class ChannelAdminLogEventActionChangeEmojiStickerSet extends VirtualClass<{ prevStickerset: Api.TypeInputStickerSet; newStickerset: Api.TypeInputStickerSet; }> { prevStickerset: Api.TypeInputStickerSet; newStickerset: Api.TypeInputStickerSet; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionChangeEmojiStickerSet; + } export class ChannelAdminLogEventActionToggleSignatureProfiles extends VirtualClass<{ newValue: Bool; }> { newValue: Bool; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionToggleSignatureProfiles; + } export class ChannelAdminLogEventActionParticipantSubExtend extends VirtualClass<{ prevParticipant: Api.TypeChannelParticipant; newParticipant: Api.TypeChannelParticipant; }> { prevParticipant: Api.TypeChannelParticipant; newParticipant: Api.TypeChannelParticipant; - }; + static fromReader(reader: Reader): ChannelAdminLogEventActionParticipantSubExtend; + } export class ChannelAdminLogEvent extends VirtualClass<{ id: long; date: int; @@ -7200,9 +8080,10 @@ namespace Api { date: int; userId: long; action: Api.TypeChannelAdminLogEventAction; - }; + static fromReader(reader: Reader): ChannelAdminLogEvent; + } export class ChannelAdminLogEventsFilter extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; join?: true; leave?: true; invite?: true; @@ -7223,7 +8104,7 @@ namespace Api { forums?: true; subExtend?: true; } | void> { - // flags: undefined; + // flags: Api.Type; join?: true; leave?: true; invite?: true; @@ -7243,60 +8124,68 @@ namespace Api { send?: true; forums?: true; subExtend?: true; - }; + static fromReader(reader: Reader): ChannelAdminLogEventsFilter; + } export class PopularContact extends VirtualClass<{ clientId: long; importers: int; }> { clientId: long; importers: int; - }; + static fromReader(reader: Reader): PopularContact; + } export class RecentMeUrlUnknown extends VirtualClass<{ url: string; }> { url: string; - }; + static fromReader(reader: Reader): RecentMeUrlUnknown; + } export class RecentMeUrlUser extends VirtualClass<{ url: string; userId: long; }> { url: string; userId: long; - }; + static fromReader(reader: Reader): RecentMeUrlUser; + } export class RecentMeUrlChat extends VirtualClass<{ url: string; chatId: long; }> { url: string; chatId: long; - }; + static fromReader(reader: Reader): RecentMeUrlChat; + } export class RecentMeUrlChatInvite extends VirtualClass<{ url: string; chatInvite: Api.TypeChatInvite; }> { url: string; chatInvite: Api.TypeChatInvite; - }; + static fromReader(reader: Reader): RecentMeUrlChatInvite; + } export class RecentMeUrlStickerSet extends VirtualClass<{ url: string; set: Api.TypeStickerSetCovered; }> { url: string; set: Api.TypeStickerSetCovered; - }; + static fromReader(reader: Reader): RecentMeUrlStickerSet; + } export class InputSingleMedia extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; media: Api.TypeInputMedia; randomId: long; message: string; entities?: Api.TypeMessageEntity[]; }> { - // flags: undefined; + // flags: Api.Type; media: Api.TypeInputMedia; randomId: long; message: string; entities?: Api.TypeMessageEntity[]; - }; + static fromReader(reader: Reader): InputSingleMedia; + } export class WebAuthorization extends VirtualClass<{ hash: long; botId: long; @@ -7317,45 +8206,55 @@ namespace Api { dateActive: int; ip: string; region: string; - }; + static fromReader(reader: Reader): WebAuthorization; + } export class InputMessageID extends VirtualClass<{ id: int; }> { id: int; - }; + static fromReader(reader: Reader): InputMessageID; + } export class InputMessageReplyTo extends VirtualClass<{ id: int; }> { id: int; - }; - export class InputMessagePinned extends VirtualClass {}; + static fromReader(reader: Reader): InputMessageReplyTo; + } + export class InputMessagePinned extends VirtualClass { + static fromReader(reader: Reader): InputMessagePinned; + } export class InputMessageCallbackQuery extends VirtualClass<{ id: int; queryId: long; }> { id: int; queryId: long; - }; + static fromReader(reader: Reader): InputMessageCallbackQuery; + } export class InputDialogPeer extends VirtualClass<{ peer: Api.TypeInputPeer; }> { peer: Api.TypeInputPeer; - }; + static fromReader(reader: Reader): InputDialogPeer; + } export class InputDialogPeerFolder extends VirtualClass<{ folderId: int; }> { folderId: int; - }; + static fromReader(reader: Reader): InputDialogPeerFolder; + } export class DialogPeer extends VirtualClass<{ peer: Api.TypePeer; }> { peer: Api.TypePeer; - }; + static fromReader(reader: Reader): DialogPeer; + } export class DialogPeerFolder extends VirtualClass<{ folderId: int; }> { folderId: int; - }; + static fromReader(reader: Reader): DialogPeerFolder; + } export class FileHash extends VirtualClass<{ offset: long; limit: int; @@ -7364,14 +8263,16 @@ namespace Api { offset: long; limit: int; hash: bytes; - }; + static fromReader(reader: Reader): FileHash; + } export class InputClientProxy extends VirtualClass<{ address: string; port: int; }> { address: string; port: int; - }; + static fromReader(reader: Reader): InputClientProxy; + } export class InputSecureFileUploaded extends VirtualClass<{ id: long; parts: int; @@ -7384,15 +8285,19 @@ namespace Api { md5Checksum: string; fileHash: bytes; secret: bytes; - }; + static fromReader(reader: Reader): InputSecureFileUploaded; + } export class InputSecureFile extends VirtualClass<{ id: long; accessHash: long; }> { id: long; accessHash: long; - }; - export class SecureFileEmpty extends VirtualClass {}; + static fromReader(reader: Reader): InputSecureFile; + } + export class SecureFileEmpty extends VirtualClass { + static fromReader(reader: Reader): SecureFileEmpty; + } export class SecureFile extends VirtualClass<{ id: long; accessHash: long; @@ -7409,7 +8314,8 @@ namespace Api { date: int; fileHash: bytes; secret: bytes; - }; + static fromReader(reader: Reader): SecureFile; + } export class SecureData extends VirtualClass<{ data: bytes; dataHash: bytes; @@ -7418,32 +8324,61 @@ namespace Api { data: bytes; dataHash: bytes; secret: bytes; - }; + static fromReader(reader: Reader): SecureData; + } export class SecurePlainPhone extends VirtualClass<{ phone: string; }> { phone: string; - }; + static fromReader(reader: Reader): SecurePlainPhone; + } export class SecurePlainEmail extends VirtualClass<{ email: string; }> { email: string; - }; - export class SecureValueTypePersonalDetails extends VirtualClass {}; - export class SecureValueTypePassport extends VirtualClass {}; - export class SecureValueTypeDriverLicense extends VirtualClass {}; - export class SecureValueTypeIdentityCard extends VirtualClass {}; - export class SecureValueTypeInternalPassport extends VirtualClass {}; - export class SecureValueTypeAddress extends VirtualClass {}; - export class SecureValueTypeUtilityBill extends VirtualClass {}; - export class SecureValueTypeBankStatement extends VirtualClass {}; - export class SecureValueTypeRentalAgreement extends VirtualClass {}; - export class SecureValueTypePassportRegistration extends VirtualClass {}; - export class SecureValueTypeTemporaryRegistration extends VirtualClass {}; - export class SecureValueTypePhone extends VirtualClass {}; - export class SecureValueTypeEmail extends VirtualClass {}; + static fromReader(reader: Reader): SecurePlainEmail; + } + export class SecureValueTypePersonalDetails extends VirtualClass { + static fromReader(reader: Reader): SecureValueTypePersonalDetails; + } + export class SecureValueTypePassport extends VirtualClass { + static fromReader(reader: Reader): SecureValueTypePassport; + } + export class SecureValueTypeDriverLicense extends VirtualClass { + static fromReader(reader: Reader): SecureValueTypeDriverLicense; + } + export class SecureValueTypeIdentityCard extends VirtualClass { + static fromReader(reader: Reader): SecureValueTypeIdentityCard; + } + export class SecureValueTypeInternalPassport extends VirtualClass { + static fromReader(reader: Reader): SecureValueTypeInternalPassport; + } + export class SecureValueTypeAddress extends VirtualClass { + static fromReader(reader: Reader): SecureValueTypeAddress; + } + export class SecureValueTypeUtilityBill extends VirtualClass { + static fromReader(reader: Reader): SecureValueTypeUtilityBill; + } + export class SecureValueTypeBankStatement extends VirtualClass { + static fromReader(reader: Reader): SecureValueTypeBankStatement; + } + export class SecureValueTypeRentalAgreement extends VirtualClass { + static fromReader(reader: Reader): SecureValueTypeRentalAgreement; + } + export class SecureValueTypePassportRegistration extends VirtualClass { + static fromReader(reader: Reader): SecureValueTypePassportRegistration; + } + export class SecureValueTypeTemporaryRegistration extends VirtualClass { + static fromReader(reader: Reader): SecureValueTypeTemporaryRegistration; + } + export class SecureValueTypePhone extends VirtualClass { + static fromReader(reader: Reader): SecureValueTypePhone; + } + export class SecureValueTypeEmail extends VirtualClass { + static fromReader(reader: Reader): SecureValueTypeEmail; + } export class SecureValue extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; type: Api.TypeSecureValueType; data?: Api.TypeSecureData; frontSide?: Api.TypeSecureFile; @@ -7454,7 +8389,7 @@ namespace Api { plainData?: Api.TypeSecurePlainData; hash: bytes; }> { - // flags: undefined; + // flags: Api.Type; type: Api.TypeSecureValueType; data?: Api.TypeSecureData; frontSide?: Api.TypeSecureFile; @@ -7464,9 +8399,10 @@ namespace Api { files?: Api.TypeSecureFile[]; plainData?: Api.TypeSecurePlainData; hash: bytes; - }; + static fromReader(reader: Reader): SecureValue; + } export class InputSecureValue extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; type: Api.TypeSecureValueType; data?: Api.TypeSecureData; frontSide?: Api.TypeInputSecureFile; @@ -7476,7 +8412,7 @@ namespace Api { files?: Api.TypeInputSecureFile[]; plainData?: Api.TypeSecurePlainData; }> { - // flags: undefined; + // flags: Api.Type; type: Api.TypeSecureValueType; data?: Api.TypeSecureData; frontSide?: Api.TypeInputSecureFile; @@ -7485,14 +8421,16 @@ namespace Api { translation?: Api.TypeInputSecureFile[]; files?: Api.TypeInputSecureFile[]; plainData?: Api.TypeSecurePlainData; - }; + static fromReader(reader: Reader): InputSecureValue; + } export class SecureValueHash extends VirtualClass<{ type: Api.TypeSecureValueType; hash: bytes; }> { type: Api.TypeSecureValueType; hash: bytes; - }; + static fromReader(reader: Reader): SecureValueHash; + } export class SecureValueErrorData extends VirtualClass<{ type: Api.TypeSecureValueType; dataHash: bytes; @@ -7503,7 +8441,8 @@ namespace Api { dataHash: bytes; field: string; text: string; - }; + static fromReader(reader: Reader): SecureValueErrorData; + } export class SecureValueErrorFrontSide extends VirtualClass<{ type: Api.TypeSecureValueType; fileHash: bytes; @@ -7512,7 +8451,8 @@ namespace Api { type: Api.TypeSecureValueType; fileHash: bytes; text: string; - }; + static fromReader(reader: Reader): SecureValueErrorFrontSide; + } export class SecureValueErrorReverseSide extends VirtualClass<{ type: Api.TypeSecureValueType; fileHash: bytes; @@ -7521,7 +8461,8 @@ namespace Api { type: Api.TypeSecureValueType; fileHash: bytes; text: string; - }; + static fromReader(reader: Reader): SecureValueErrorReverseSide; + } export class SecureValueErrorSelfie extends VirtualClass<{ type: Api.TypeSecureValueType; fileHash: bytes; @@ -7530,7 +8471,8 @@ namespace Api { type: Api.TypeSecureValueType; fileHash: bytes; text: string; - }; + static fromReader(reader: Reader): SecureValueErrorSelfie; + } export class SecureValueErrorFile extends VirtualClass<{ type: Api.TypeSecureValueType; fileHash: bytes; @@ -7539,7 +8481,8 @@ namespace Api { type: Api.TypeSecureValueType; fileHash: bytes; text: string; - }; + static fromReader(reader: Reader): SecureValueErrorFile; + } export class SecureValueErrorFiles extends VirtualClass<{ type: Api.TypeSecureValueType; fileHash: bytes[]; @@ -7548,7 +8491,8 @@ namespace Api { type: Api.TypeSecureValueType; fileHash: bytes[]; text: string; - }; + static fromReader(reader: Reader): SecureValueErrorFiles; + } export class SecureValueError extends VirtualClass<{ type: Api.TypeSecureValueType; hash: bytes; @@ -7557,7 +8501,8 @@ namespace Api { type: Api.TypeSecureValueType; hash: bytes; text: string; - }; + static fromReader(reader: Reader): SecureValueError; + } export class SecureValueErrorTranslationFile extends VirtualClass<{ type: Api.TypeSecureValueType; fileHash: bytes; @@ -7566,7 +8511,8 @@ namespace Api { type: Api.TypeSecureValueType; fileHash: bytes; text: string; - }; + static fromReader(reader: Reader): SecureValueErrorTranslationFile; + } export class SecureValueErrorTranslationFiles extends VirtualClass<{ type: Api.TypeSecureValueType; fileHash: bytes[]; @@ -7575,7 +8521,8 @@ namespace Api { type: Api.TypeSecureValueType; fileHash: bytes[]; text: string; - }; + static fromReader(reader: Reader): SecureValueErrorTranslationFiles; + } export class SecureCredentialsEncrypted extends VirtualClass<{ data: bytes; hash: bytes; @@ -7584,7 +8531,8 @@ namespace Api { data: bytes; hash: bytes; secret: bytes; - }; + static fromReader(reader: Reader): SecureCredentialsEncrypted; + } export class SavedPhoneContact extends VirtualClass<{ phone: string; firstName: string; @@ -7595,8 +8543,11 @@ namespace Api { firstName: string; lastName: string; date: int; - }; - export class PasswordKdfAlgoUnknown extends VirtualClass {}; + static fromReader(reader: Reader): SavedPhoneContact; + } + export class PasswordKdfAlgoUnknown extends VirtualClass { + static fromReader(reader: Reader): PasswordKdfAlgoUnknown; + } export class PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow extends VirtualClass<{ salt1: bytes; salt2: bytes; @@ -7607,18 +8558,23 @@ namespace Api { salt2: bytes; g: int; p: bytes; - }; - export class SecurePasswordKdfAlgoUnknown extends VirtualClass {}; + static fromReader(reader: Reader): PasswordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow; + } + export class SecurePasswordKdfAlgoUnknown extends VirtualClass { + static fromReader(reader: Reader): SecurePasswordKdfAlgoUnknown; + } export class SecurePasswordKdfAlgoPBKDF2HMACSHA512iter100000 extends VirtualClass<{ salt: bytes; }> { salt: bytes; - }; + static fromReader(reader: Reader): SecurePasswordKdfAlgoPBKDF2HMACSHA512iter100000; + } export class SecurePasswordKdfAlgoSHA512 extends VirtualClass<{ salt: bytes; }> { salt: bytes; - }; + static fromReader(reader: Reader): SecurePasswordKdfAlgoSHA512; + } export class SecureSecretSettings extends VirtualClass<{ secureAlgo: Api.TypeSecurePasswordKdfAlgo; secureSecret: bytes; @@ -7627,8 +8583,11 @@ namespace Api { secureAlgo: Api.TypeSecurePasswordKdfAlgo; secureSecret: bytes; secureSecretId: long; - }; - export class InputCheckPasswordEmpty extends VirtualClass {}; + static fromReader(reader: Reader): SecureSecretSettings; + } + export class InputCheckPasswordEmpty extends VirtualClass { + static fromReader(reader: Reader): InputCheckPasswordEmpty; + } export class InputCheckPasswordSRP extends VirtualClass<{ srpId: long; A: bytes; @@ -7637,25 +8596,28 @@ namespace Api { srpId: long; A: bytes; M1: bytes; - }; + static fromReader(reader: Reader): InputCheckPasswordSRP; + } export class SecureRequiredType extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; nativeNames?: true; selfieRequired?: true; translationRequired?: true; type: Api.TypeSecureValueType; }> { - // flags: undefined; + // flags: Api.Type; nativeNames?: true; selfieRequired?: true; translationRequired?: true; type: Api.TypeSecureValueType; - }; + static fromReader(reader: Reader): SecureRequiredType; + } export class SecureRequiredTypeOneOf extends VirtualClass<{ types: Api.TypeSecureRequiredType[]; }> { types: Api.TypeSecureRequiredType[]; - }; + static fromReader(reader: Reader): SecureRequiredTypeOneOf; + } export class InputAppEvent extends VirtualClass<{ time: double; type: string; @@ -7666,42 +8628,51 @@ namespace Api { type: string; peer: long; data: Api.TypeJSONValue; - }; + static fromReader(reader: Reader): InputAppEvent; + } export class JsonObjectValue extends VirtualClass<{ key: string; value: Api.TypeJSONValue; }> { key: string; value: Api.TypeJSONValue; - }; - export class JsonNull extends VirtualClass {}; + static fromReader(reader: Reader): JsonObjectValue; + } + export class JsonNull extends VirtualClass { + static fromReader(reader: Reader): JsonNull; + } export class JsonBool extends VirtualClass<{ value: Bool; }> { value: Bool; - }; + static fromReader(reader: Reader): JsonBool; + } export class JsonNumber extends VirtualClass<{ value: double; }> { value: double; - }; + static fromReader(reader: Reader): JsonNumber; + } export class JsonString extends VirtualClass<{ value: string; }> { value: string; - }; + static fromReader(reader: Reader): JsonString; + } export class JsonArray extends VirtualClass<{ value: Api.TypeJSONValue[]; }> { value: Api.TypeJSONValue[]; - }; + static fromReader(reader: Reader): JsonArray; + } export class JsonObject extends VirtualClass<{ value: Api.TypeJSONObjectValue[]; }> { value: Api.TypeJSONObjectValue[]; - }; + static fromReader(reader: Reader): JsonObject; + } export class PageTableCell extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; header?: true; alignCenter?: true; alignRight?: true; @@ -7711,7 +8682,7 @@ namespace Api { colspan?: int; rowspan?: int; } | void> { - // flags: undefined; + // flags: Api.Type; header?: true; alignCenter?: true; alignRight?: true; @@ -7720,45 +8691,52 @@ namespace Api { text?: Api.TypeRichText; colspan?: int; rowspan?: int; - }; + static fromReader(reader: Reader): PageTableCell; + } export class PageTableRow extends VirtualClass<{ cells: Api.TypePageTableCell[]; }> { cells: Api.TypePageTableCell[]; - }; + static fromReader(reader: Reader): PageTableRow; + } export class PageCaption extends VirtualClass<{ text: Api.TypeRichText; credit: Api.TypeRichText; }> { text: Api.TypeRichText; credit: Api.TypeRichText; - }; + static fromReader(reader: Reader): PageCaption; + } export class PageListItemText extends VirtualClass<{ text: Api.TypeRichText; }> { text: Api.TypeRichText; - }; + static fromReader(reader: Reader): PageListItemText; + } export class PageListItemBlocks extends VirtualClass<{ blocks: Api.TypePageBlock[]; }> { blocks: Api.TypePageBlock[]; - }; + static fromReader(reader: Reader): PageListItemBlocks; + } export class PageListOrderedItemText extends VirtualClass<{ num: string; text: Api.TypeRichText; }> { num: string; text: Api.TypeRichText; - }; + static fromReader(reader: Reader): PageListOrderedItemText; + } export class PageListOrderedItemBlocks extends VirtualClass<{ num: string; blocks: Api.TypePageBlock[]; }> { num: string; blocks: Api.TypePageBlock[]; - }; + static fromReader(reader: Reader): PageListOrderedItemBlocks; + } export class PageRelatedArticle extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; url: string; webpageId: long; title?: string; @@ -7767,7 +8745,7 @@ namespace Api { author?: string; publishedDate?: int; }> { - // flags: undefined; + // flags: Api.Type; url: string; webpageId: long; title?: string; @@ -7775,9 +8753,10 @@ namespace Api { photoId?: long; author?: string; publishedDate?: int; - }; + static fromReader(reader: Reader): PageRelatedArticle; + } export class Page extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; part?: true; rtl?: true; v2?: true; @@ -7787,7 +8766,7 @@ namespace Api { documents: Api.TypeDocument[]; views?: int; }> { - // flags: undefined; + // flags: Api.Type; part?: true; rtl?: true; v2?: true; @@ -7796,17 +8775,19 @@ namespace Api { photos: Api.TypePhoto[]; documents: Api.TypeDocument[]; views?: int; - }; + static fromReader(reader: Reader): Page; + } export class PollAnswer extends VirtualClass<{ text: Api.TypeTextWithEntities; option: bytes; }> { text: Api.TypeTextWithEntities; option: bytes; - }; + static fromReader(reader: Reader): PollAnswer; + } export class Poll extends VirtualClass<{ id: long; - // flags: undefined; + // flags: Api.Type; closed?: true; publicVoters?: true; multipleChoice?: true; @@ -7817,7 +8798,7 @@ namespace Api { closeDate?: int; }> { id: long; - // flags: undefined; + // flags: Api.Type; closed?: true; publicVoters?: true; multipleChoice?: true; @@ -7826,22 +8807,24 @@ namespace Api { answers: Api.TypePollAnswer[]; closePeriod?: int; closeDate?: int; - }; + static fromReader(reader: Reader): Poll; + } export class PollAnswerVoters extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; chosen?: true; correct?: true; option: bytes; voters: int; }> { - // flags: undefined; + // flags: Api.Type; chosen?: true; correct?: true; option: bytes; voters: int; - }; + static fromReader(reader: Reader): PollAnswerVoters; + } export class PollResults extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; min?: true; results?: Api.TypePollAnswerVoters[]; totalVoters?: int; @@ -7849,26 +8832,29 @@ namespace Api { solution?: string; solutionEntities?: Api.TypeMessageEntity[]; } | void> { - // flags: undefined; + // flags: Api.Type; min?: true; results?: Api.TypePollAnswerVoters[]; totalVoters?: int; recentVoters?: Api.TypePeer[]; solution?: string; solutionEntities?: Api.TypeMessageEntity[]; - }; + static fromReader(reader: Reader): PollResults; + } export class ChatOnlines extends VirtualClass<{ onlines: int; }> { onlines: int; - }; + static fromReader(reader: Reader): ChatOnlines; + } export class StatsURL extends VirtualClass<{ url: string; }> { url: string; - }; + static fromReader(reader: Reader): StatsURL; + } export class ChatAdminRights extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; changeInfo?: true; postMessages?: true; editMessages?: true; @@ -7885,7 +8871,7 @@ namespace Api { editStories?: true; deleteStories?: true; } | void> { - // flags: undefined; + // flags: Api.Type; changeInfo?: true; postMessages?: true; editMessages?: true; @@ -7901,9 +8887,10 @@ namespace Api { postStories?: true; editStories?: true; deleteStories?: true; - }; + static fromReader(reader: Reader): ChatAdminRights; + } export class ChatBannedRights extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; viewMessages?: true; sendMessages?: true; sendMedia?: true; @@ -7926,7 +8913,7 @@ namespace Api { sendPlain?: true; untilDate: int; }> { - // flags: undefined; + // flags: Api.Type; viewMessages?: true; sendMessages?: true; sendMedia?: true; @@ -7948,26 +8935,30 @@ namespace Api { sendDocs?: true; sendPlain?: true; untilDate: int; - }; + static fromReader(reader: Reader): ChatBannedRights; + } export class InputWallPaper extends VirtualClass<{ id: long; accessHash: long; }> { id: long; accessHash: long; - }; + static fromReader(reader: Reader): InputWallPaper; + } export class InputWallPaperSlug extends VirtualClass<{ slug: string; }> { slug: string; - }; + static fromReader(reader: Reader): InputWallPaperSlug; + } export class InputWallPaperNoFile extends VirtualClass<{ id: long; }> { id: long; - }; + static fromReader(reader: Reader): InputWallPaperNoFile; + } export class CodeSettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; allowFlashcall?: true; currentNumber?: true; allowAppHash?: true; @@ -7978,7 +8969,7 @@ namespace Api { token?: string; appSandbox?: Bool; } | void> { - // flags: undefined; + // flags: Api.Type; allowFlashcall?: true; currentNumber?: true; allowAppHash?: true; @@ -7988,9 +8979,10 @@ namespace Api { logoutTokens?: bytes[]; token?: string; appSandbox?: Bool; - }; + static fromReader(reader: Reader): CodeSettings; + } export class WallPaperSettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; blur?: true; motion?: true; backgroundColor?: int; @@ -8001,7 +8993,7 @@ namespace Api { rotation?: int; emoticon?: string; } | void> { - // flags: undefined; + // flags: Api.Type; blur?: true; motion?: true; backgroundColor?: int; @@ -8011,9 +9003,10 @@ namespace Api { intensity?: int; rotation?: int; emoticon?: string; - }; + static fromReader(reader: Reader): WallPaperSettings; + } export class AutoDownloadSettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; disabled?: true; videoPreloadLarge?: true; audioPreloadNext?: true; @@ -8026,7 +9019,7 @@ namespace Api { smallQueueActiveOperationsMax: int; largeQueueActiveOperationsMax: int; }> { - // flags: undefined; + // flags: Api.Type; disabled?: true; videoPreloadLarge?: true; audioPreloadNext?: true; @@ -8038,21 +9031,24 @@ namespace Api { videoUploadMaxbitrate: int; smallQueueActiveOperationsMax: int; largeQueueActiveOperationsMax: int; - }; + static fromReader(reader: Reader): AutoDownloadSettings; + } export class EmojiKeyword extends VirtualClass<{ keyword: string; emoticons: string[]; }> { keyword: string; emoticons: string[]; - }; + static fromReader(reader: Reader): EmojiKeyword; + } export class EmojiKeywordDeleted extends VirtualClass<{ keyword: string; emoticons: string[]; }> { keyword: string; emoticons: string[]; - }; + static fromReader(reader: Reader): EmojiKeywordDeleted; + } export class EmojiKeywordsDifference extends VirtualClass<{ langCode: string; fromVersion: int; @@ -8063,19 +9059,22 @@ namespace Api { fromVersion: int; version: int; keywords: Api.TypeEmojiKeyword[]; - }; + static fromReader(reader: Reader): EmojiKeywordsDifference; + } export class EmojiURL extends VirtualClass<{ url: string; }> { url: string; - }; + static fromReader(reader: Reader): EmojiURL; + } export class EmojiLanguage extends VirtualClass<{ langCode: string; }> { langCode: string; - }; + static fromReader(reader: Reader): EmojiLanguage; + } export class Folder extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; autofillNewBroadcasts?: true; autofillPublicGroups?: true; autofillNewCorrespondents?: true; @@ -8083,53 +9082,63 @@ namespace Api { title: string; photo?: Api.TypeChatPhoto; }> { - // flags: undefined; + // flags: Api.Type; autofillNewBroadcasts?: true; autofillPublicGroups?: true; autofillNewCorrespondents?: true; id: int; title: string; photo?: Api.TypeChatPhoto; - }; + static fromReader(reader: Reader): Folder; + } export class InputFolderPeer extends VirtualClass<{ peer: Api.TypeInputPeer; folderId: int; }> { peer: Api.TypeInputPeer; folderId: int; - }; + static fromReader(reader: Reader): InputFolderPeer; + } export class FolderPeer extends VirtualClass<{ peer: Api.TypePeer; folderId: int; }> { peer: Api.TypePeer; folderId: int; - }; + static fromReader(reader: Reader): FolderPeer; + } export class UrlAuthResultRequest extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; requestWriteAccess?: true; bot: Api.TypeUser; domain: string; }> { - // flags: undefined; + // flags: Api.Type; requestWriteAccess?: true; bot: Api.TypeUser; domain: string; - }; + static fromReader(reader: Reader): UrlAuthResultRequest; + } export class UrlAuthResultAccepted extends VirtualClass<{ url: string; }> { url: string; - }; - export class UrlAuthResultDefault extends VirtualClass {}; - export class ChannelLocationEmpty extends VirtualClass {}; + static fromReader(reader: Reader): UrlAuthResultAccepted; + } + export class UrlAuthResultDefault extends VirtualClass { + static fromReader(reader: Reader): UrlAuthResultDefault; + } + export class ChannelLocationEmpty extends VirtualClass { + static fromReader(reader: Reader): ChannelLocationEmpty; + } export class ChannelLocation extends VirtualClass<{ geoPoint: Api.TypeGeoPoint; address: string; }> { geoPoint: Api.TypeGeoPoint; address: string; - }; + static fromReader(reader: Reader): ChannelLocation; + } export class PeerLocated extends VirtualClass<{ peer: Api.TypePeer; expires: int; @@ -8138,12 +9147,14 @@ namespace Api { peer: Api.TypePeer; expires: int; distance: int; - }; + static fromReader(reader: Reader): PeerLocated; + } export class PeerSelfLocated extends VirtualClass<{ expires: int; }> { expires: int; - }; + static fromReader(reader: Reader): PeerSelfLocated; + } export class RestrictionReason extends VirtualClass<{ platform: string; reason: string; @@ -8152,21 +9163,24 @@ namespace Api { platform: string; reason: string; text: string; - }; + static fromReader(reader: Reader): RestrictionReason; + } export class InputTheme extends VirtualClass<{ id: long; accessHash: long; }> { id: long; accessHash: long; - }; + static fromReader(reader: Reader): InputTheme; + } export class InputThemeSlug extends VirtualClass<{ slug: string; }> { slug: string; - }; + static fromReader(reader: Reader): InputThemeSlug; + } export class Theme extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; creator?: true; default?: true; forChat?: true; @@ -8179,7 +9193,7 @@ namespace Api { emoticon?: string; installsCount?: int; }> { - // flags: undefined; + // flags: Api.Type; creator?: true; default?: true; forChat?: true; @@ -8191,14 +9205,25 @@ namespace Api { settings?: Api.TypeThemeSettings[]; emoticon?: string; installsCount?: int; - }; - export class BaseThemeClassic extends VirtualClass {}; - export class BaseThemeDay extends VirtualClass {}; - export class BaseThemeNight extends VirtualClass {}; - export class BaseThemeTinted extends VirtualClass {}; - export class BaseThemeArctic extends VirtualClass {}; + static fromReader(reader: Reader): Theme; + } + export class BaseThemeClassic extends VirtualClass { + static fromReader(reader: Reader): BaseThemeClassic; + } + export class BaseThemeDay extends VirtualClass { + static fromReader(reader: Reader): BaseThemeDay; + } + export class BaseThemeNight extends VirtualClass { + static fromReader(reader: Reader): BaseThemeNight; + } + export class BaseThemeTinted extends VirtualClass { + static fromReader(reader: Reader): BaseThemeTinted; + } + export class BaseThemeArctic extends VirtualClass { + static fromReader(reader: Reader): BaseThemeArctic; + } export class InputThemeSettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; messageColorsAnimated?: true; baseTheme: Api.TypeBaseTheme; accentColor: int; @@ -8207,7 +9232,7 @@ namespace Api { wallpaper?: Api.TypeInputWallPaper; wallpaperSettings?: Api.TypeWallPaperSettings; }> { - // flags: undefined; + // flags: Api.Type; messageColorsAnimated?: true; baseTheme: Api.TypeBaseTheme; accentColor: int; @@ -8215,9 +9240,10 @@ namespace Api { messageColors?: int[]; wallpaper?: Api.TypeInputWallPaper; wallpaperSettings?: Api.TypeWallPaperSettings; - }; + static fromReader(reader: Reader): InputThemeSettings; + } export class ThemeSettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; messageColorsAnimated?: true; baseTheme: Api.TypeBaseTheme; accentColor: int; @@ -8225,59 +9251,65 @@ namespace Api { messageColors?: int[]; wallpaper?: Api.TypeWallPaper; }> { - // flags: undefined; + // flags: Api.Type; messageColorsAnimated?: true; baseTheme: Api.TypeBaseTheme; accentColor: int; outboxAccentColor?: int; messageColors?: int[]; wallpaper?: Api.TypeWallPaper; - }; + static fromReader(reader: Reader): ThemeSettings; + } export class WebPageAttributeTheme extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; documents?: Api.TypeDocument[]; settings?: Api.TypeThemeSettings; } | void> { - // flags: undefined; + // flags: Api.Type; documents?: Api.TypeDocument[]; settings?: Api.TypeThemeSettings; - }; + static fromReader(reader: Reader): WebPageAttributeTheme; + } export class WebPageAttributeStory extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; id: int; story?: Api.TypeStoryItem; }> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; id: int; story?: Api.TypeStoryItem; - }; + static fromReader(reader: Reader): WebPageAttributeStory; + } export class WebPageAttributeStickerSet extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; emojis?: true; textColor?: true; stickers: Api.TypeDocument[]; }> { - // flags: undefined; + // flags: Api.Type; emojis?: true; textColor?: true; stickers: Api.TypeDocument[]; - }; + static fromReader(reader: Reader): WebPageAttributeStickerSet; + } export class WebPageAttributeUniqueStarGift extends VirtualClass<{ gift: Api.TypeStarGift; }> { gift: Api.TypeStarGift; - }; + static fromReader(reader: Reader): WebPageAttributeUniqueStarGift; + } export class BankCardOpenUrl extends VirtualClass<{ url: string; name: string; }> { url: string; name: string; - }; + static fromReader(reader: Reader): BankCardOpenUrl; + } export class DialogFilter extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; contacts?: true; nonContacts?: true; groups?: true; @@ -8295,7 +9327,7 @@ namespace Api { includePeers: Api.TypeInputPeer[]; excludePeers: Api.TypeInputPeer[]; }> { - // flags: undefined; + // flags: Api.Type; contacts?: true; nonContacts?: true; groups?: true; @@ -8312,10 +9344,13 @@ namespace Api { pinnedPeers: Api.TypeInputPeer[]; includePeers: Api.TypeInputPeer[]; excludePeers: Api.TypeInputPeer[]; - }; - export class DialogFilterDefault extends VirtualClass {}; + static fromReader(reader: Reader): DialogFilter; + } + export class DialogFilterDefault extends VirtualClass { + static fromReader(reader: Reader): DialogFilterDefault; + } export class DialogFilterChatlist extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; hasMyInvites?: true; titleNoanimate?: true; id: int; @@ -8325,7 +9360,7 @@ namespace Api { pinnedPeers: Api.TypeInputPeer[]; includePeers: Api.TypeInputPeer[]; }> { - // flags: undefined; + // flags: Api.Type; hasMyInvites?: true; titleNoanimate?: true; id: int; @@ -8334,76 +9369,86 @@ namespace Api { color?: int; pinnedPeers: Api.TypeInputPeer[]; includePeers: Api.TypeInputPeer[]; - }; + static fromReader(reader: Reader): DialogFilterChatlist; + } export class DialogFilterSuggested extends VirtualClass<{ filter: Api.TypeDialogFilter; description: string; }> { filter: Api.TypeDialogFilter; description: string; - }; + static fromReader(reader: Reader): DialogFilterSuggested; + } export class StatsDateRangeDays extends VirtualClass<{ minDate: int; maxDate: int; }> { minDate: int; maxDate: int; - }; + static fromReader(reader: Reader): StatsDateRangeDays; + } export class StatsAbsValueAndPrev extends VirtualClass<{ current: double; previous: double; }> { current: double; previous: double; - }; + static fromReader(reader: Reader): StatsAbsValueAndPrev; + } export class StatsPercentValue extends VirtualClass<{ part: double; total: double; }> { part: double; total: double; - }; + static fromReader(reader: Reader): StatsPercentValue; + } export class StatsGraphAsync extends VirtualClass<{ token: string; }> { token: string; - }; + static fromReader(reader: Reader): StatsGraphAsync; + } export class StatsGraphError extends VirtualClass<{ error: string; }> { error: string; - }; + static fromReader(reader: Reader): StatsGraphError; + } export class StatsGraph extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; json: Api.TypeDataJSON; zoomToken?: string; }> { - // flags: undefined; + // flags: Api.Type; json: Api.TypeDataJSON; zoomToken?: string; - }; + static fromReader(reader: Reader): StatsGraph; + } export class VideoSize extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; type: string; w: int; h: int; size: int; videoStartTs?: double; }> { - // flags: undefined; + // flags: Api.Type; type: string; w: int; h: int; size: int; videoStartTs?: double; - }; + static fromReader(reader: Reader): VideoSize; + } export class VideoSizeEmojiMarkup extends VirtualClass<{ emojiId: long; backgroundColors: int[]; }> { emojiId: long; backgroundColors: int[]; - }; + static fromReader(reader: Reader): VideoSizeEmojiMarkup; + } export class VideoSizeStickerMarkup extends VirtualClass<{ stickerset: Api.TypeInputStickerSet; stickerId: long; @@ -8412,7 +9457,8 @@ namespace Api { stickerset: Api.TypeInputStickerSet; stickerId: long; backgroundColors: int[]; - }; + static fromReader(reader: Reader): VideoSizeStickerMarkup; + } export class StatsGroupTopPoster extends VirtualClass<{ userId: long; messages: int; @@ -8421,7 +9467,8 @@ namespace Api { userId: long; messages: int; avgChars: int; - }; + static fromReader(reader: Reader): StatsGroupTopPoster; + } export class StatsGroupTopAdmin extends VirtualClass<{ userId: long; deleted: int; @@ -8432,42 +9479,46 @@ namespace Api { deleted: int; kicked: int; banned: int; - }; + static fromReader(reader: Reader): StatsGroupTopAdmin; + } export class StatsGroupTopInviter extends VirtualClass<{ userId: long; invitations: int; }> { userId: long; invitations: int; - }; + static fromReader(reader: Reader): StatsGroupTopInviter; + } export class GlobalPrivacySettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; archiveAndMuteNewNoncontactPeers?: true; keepArchivedUnmuted?: true; keepArchivedFolders?: true; hideReadMarks?: true; newNoncontactPeersRequirePremium?: true; } | void> { - // flags: undefined; + // flags: Api.Type; archiveAndMuteNewNoncontactPeers?: true; keepArchivedUnmuted?: true; keepArchivedFolders?: true; hideReadMarks?: true; newNoncontactPeersRequirePremium?: true; - }; + static fromReader(reader: Reader): GlobalPrivacySettings; + } export class MessageViews extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; views?: int; forwards?: int; replies?: Api.TypeMessageReplies; } | void> { - // flags: undefined; + // flags: Api.Type; views?: int; forwards?: int; replies?: Api.TypeMessageReplies; - }; + static fromReader(reader: Reader): MessageViews; + } export class MessageReplyHeader extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; replyToScheduled?: true; forumTopic?: true; quote?: true; @@ -8480,7 +9531,7 @@ namespace Api { quoteEntities?: Api.TypeMessageEntity[]; quoteOffset?: int; } | void> { - // flags: undefined; + // flags: Api.Type; replyToScheduled?: true; forumTopic?: true; quote?: true; @@ -8492,16 +9543,18 @@ namespace Api { quoteText?: string; quoteEntities?: Api.TypeMessageEntity[]; quoteOffset?: int; - }; + static fromReader(reader: Reader): MessageReplyHeader; + } export class MessageReplyStoryHeader extends VirtualClass<{ peer: Api.TypePeer; storyId: int; }> { peer: Api.TypePeer; storyId: int; - }; + static fromReader(reader: Reader): MessageReplyStoryHeader; + } export class MessageReplies extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; comments?: true; replies: int; repliesPts: int; @@ -8510,7 +9563,7 @@ namespace Api { maxId?: int; readMaxId?: int; }> { - // flags: undefined; + // flags: Api.Type; comments?: true; replies: int; repliesPts: int; @@ -8518,14 +9571,16 @@ namespace Api { channelId?: long; maxId?: int; readMaxId?: int; - }; + static fromReader(reader: Reader): MessageReplies; + } export class PeerBlocked extends VirtualClass<{ peerId: Api.TypePeer; date: int; }> { peerId: Api.TypePeer; date: int; - }; + static fromReader(reader: Reader): PeerBlocked; + } export class GroupCallDiscarded extends VirtualClass<{ id: long; accessHash: long; @@ -8534,9 +9589,10 @@ namespace Api { id: long; accessHash: long; duration: int; - }; + static fromReader(reader: Reader): GroupCallDiscarded; + } export class GroupCall extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; joinMuted?: true; canChangeJoinMuted?: true; joinDateAsc?: true; @@ -8557,7 +9613,7 @@ namespace Api { version: int; conferenceFromCall?: long; }> { - // flags: undefined; + // flags: Api.Type; joinMuted?: true; canChangeJoinMuted?: true; joinDateAsc?: true; @@ -8577,16 +9633,18 @@ namespace Api { unmutedVideoLimit: int; version: int; conferenceFromCall?: long; - }; + static fromReader(reader: Reader): GroupCall; + } export class InputGroupCall extends VirtualClass<{ id: long; accessHash: long; }> { id: long; accessHash: long; - }; + static fromReader(reader: Reader): InputGroupCall; + } export class GroupCallParticipant extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; muted?: true; left?: true; canSelfUnmute?: true; @@ -8607,7 +9665,7 @@ namespace Api { video?: Api.TypeGroupCallParticipantVideo; presentation?: Api.TypeGroupCallParticipantVideo; }> { - // flags: undefined; + // flags: Api.Type; muted?: true; left?: true; canSelfUnmute?: true; @@ -8627,15 +9685,28 @@ namespace Api { raiseHandRating?: long; video?: Api.TypeGroupCallParticipantVideo; presentation?: Api.TypeGroupCallParticipantVideo; - }; - export class InlineQueryPeerTypeSameBotPM extends VirtualClass {}; - export class InlineQueryPeerTypePM extends VirtualClass {}; - export class InlineQueryPeerTypeChat extends VirtualClass {}; - export class InlineQueryPeerTypeMegagroup extends VirtualClass {}; - export class InlineQueryPeerTypeBroadcast extends VirtualClass {}; - export class InlineQueryPeerTypeBotPM extends VirtualClass {}; + static fromReader(reader: Reader): GroupCallParticipant; + } + export class InlineQueryPeerTypeSameBotPM extends VirtualClass { + static fromReader(reader: Reader): InlineQueryPeerTypeSameBotPM; + } + export class InlineQueryPeerTypePM extends VirtualClass { + static fromReader(reader: Reader): InlineQueryPeerTypePM; + } + export class InlineQueryPeerTypeChat extends VirtualClass { + static fromReader(reader: Reader): InlineQueryPeerTypeChat; + } + export class InlineQueryPeerTypeMegagroup extends VirtualClass { + static fromReader(reader: Reader): InlineQueryPeerTypeMegagroup; + } + export class InlineQueryPeerTypeBroadcast extends VirtualClass { + static fromReader(reader: Reader): InlineQueryPeerTypeBroadcast; + } + export class InlineQueryPeerTypeBotPM extends VirtualClass { + static fromReader(reader: Reader): InlineQueryPeerTypeBotPM; + } export class ChatInviteImporter extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; requested?: true; viaChatlist?: true; userId: long; @@ -8643,14 +9714,15 @@ namespace Api { about?: string; approvedBy?: long; }> { - // flags: undefined; + // flags: Api.Type; requested?: true; viaChatlist?: true; userId: long; date: int; about?: string; approvedBy?: long; - }; + static fromReader(reader: Reader): ChatInviteImporter; + } export class ChatAdminWithInvites extends VirtualClass<{ adminId: long; invitesCount: int; @@ -8659,50 +9731,64 @@ namespace Api { adminId: long; invitesCount: int; revokedInvitesCount: int; - }; + static fromReader(reader: Reader): ChatAdminWithInvites; + } export class GroupCallParticipantVideoSourceGroup extends VirtualClass<{ semantics: string; sources: int[]; }> { semantics: string; sources: int[]; - }; + static fromReader(reader: Reader): GroupCallParticipantVideoSourceGroup; + } export class GroupCallParticipantVideo extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; paused?: true; endpoint: string; sourceGroups: Api.TypeGroupCallParticipantVideoSourceGroup[]; audioSource?: int; }> { - // flags: undefined; + // flags: Api.Type; paused?: true; endpoint: string; sourceGroups: Api.TypeGroupCallParticipantVideoSourceGroup[]; audioSource?: int; - }; - export class BotCommandScopeDefault extends VirtualClass {}; - export class BotCommandScopeUsers extends VirtualClass {}; - export class BotCommandScopeChats extends VirtualClass {}; - export class BotCommandScopeChatAdmins extends VirtualClass {}; + static fromReader(reader: Reader): GroupCallParticipantVideo; + } + export class BotCommandScopeDefault extends VirtualClass { + static fromReader(reader: Reader): BotCommandScopeDefault; + } + export class BotCommandScopeUsers extends VirtualClass { + static fromReader(reader: Reader): BotCommandScopeUsers; + } + export class BotCommandScopeChats extends VirtualClass { + static fromReader(reader: Reader): BotCommandScopeChats; + } + export class BotCommandScopeChatAdmins extends VirtualClass { + static fromReader(reader: Reader): BotCommandScopeChatAdmins; + } export class BotCommandScopePeer extends VirtualClass<{ peer: Api.TypeInputPeer; }> { peer: Api.TypeInputPeer; - }; + static fromReader(reader: Reader): BotCommandScopePeer; + } export class BotCommandScopePeerAdmins extends VirtualClass<{ peer: Api.TypeInputPeer; }> { peer: Api.TypeInputPeer; - }; + static fromReader(reader: Reader): BotCommandScopePeerAdmins; + } export class BotCommandScopePeerUser extends VirtualClass<{ peer: Api.TypeInputPeer; userId: Api.TypeInputUser; }> { peer: Api.TypeInputPeer; userId: Api.TypeInputUser; - }; + static fromReader(reader: Reader): BotCommandScopePeerUser; + } export class SponsoredMessage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; recommended?: true; canReport?: true; randomId: bytes; @@ -8717,7 +9803,7 @@ namespace Api { sponsorInfo?: string; additionalInfo?: string; }> { - // flags: undefined; + // flags: Api.Type; recommended?: true; canReport?: true; randomId: bytes; @@ -8731,7 +9817,8 @@ namespace Api { buttonText: string; sponsorInfo?: string; additionalInfo?: string; - }; + static fromReader(reader: Reader): SponsoredMessage; + } export class SearchResultsCalendarPeriod extends VirtualClass<{ date: int; minMsgId: int; @@ -8742,7 +9829,8 @@ namespace Api { minMsgId: int; maxMsgId: int; count: int; - }; + static fromReader(reader: Reader): SearchResultsCalendarPeriod; + } export class SearchResultPosition extends VirtualClass<{ msgId: int; date: int; @@ -8751,20 +9839,22 @@ namespace Api { msgId: int; date: int; offset: int; - }; + static fromReader(reader: Reader): SearchResultPosition; + } export class ReactionCount extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; chosenOrder?: int; reaction: Api.TypeReaction; count: int; }> { - // flags: undefined; + // flags: Api.Type; chosenOrder?: int; reaction: Api.TypeReaction; count: int; - }; + static fromReader(reader: Reader): ReactionCount; + } export class MessageReactions extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; min?: true; canSeeList?: true; reactionsAsTags?: true; @@ -8772,16 +9862,17 @@ namespace Api { recentReactions?: Api.TypeMessagePeerReaction[]; topReactors?: Api.TypeMessageReactor[]; }> { - // flags: undefined; + // flags: Api.Type; min?: true; canSeeList?: true; reactionsAsTags?: true; results: Api.TypeReactionCount[]; recentReactions?: Api.TypeMessagePeerReaction[]; topReactors?: Api.TypeMessageReactor[]; - }; + static fromReader(reader: Reader): MessageReactions; + } export class AvailableReaction extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; inactive?: true; premium?: true; reaction: string; @@ -8794,7 +9885,7 @@ namespace Api { aroundAnimation?: Api.TypeDocument; centerIcon?: Api.TypeDocument; }> { - // flags: undefined; + // flags: Api.Type; inactive?: true; premium?: true; reaction: string; @@ -8806,9 +9897,10 @@ namespace Api { effectAnimation: Api.TypeDocument; aroundAnimation?: Api.TypeDocument; centerIcon?: Api.TypeDocument; - }; + static fromReader(reader: Reader): AvailableReaction; + } export class MessagePeerReaction extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; big?: true; unread?: true; my?: true; @@ -8816,14 +9908,15 @@ namespace Api { date: int; reaction: Api.TypeReaction; }> { - // flags: undefined; + // flags: Api.Type; big?: true; unread?: true; my?: true; peerId: Api.TypePeer; date: int; reaction: Api.TypeReaction; - }; + static fromReader(reader: Reader): MessagePeerReaction; + } export class GroupCallStreamChannel extends VirtualClass<{ channel: int; scale: int; @@ -8832,27 +9925,30 @@ namespace Api { channel: int; scale: int; lastTimestampMs: long; - }; + static fromReader(reader: Reader): GroupCallStreamChannel; + } export class AttachMenuBotIconColor extends VirtualClass<{ name: string; color: int; }> { name: string; color: int; - }; + static fromReader(reader: Reader): AttachMenuBotIconColor; + } export class AttachMenuBotIcon extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; name: string; icon: Api.TypeDocument; colors?: Api.TypeAttachMenuBotIconColor[]; }> { - // flags: undefined; + // flags: Api.Type; name: string; icon: Api.TypeDocument; colors?: Api.TypeAttachMenuBotIconColor[]; - }; + static fromReader(reader: Reader): AttachMenuBotIcon; + } export class AttachMenuBot extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; inactive?: true; hasSettings?: true; requestWriteAccess?: true; @@ -8864,7 +9960,7 @@ namespace Api { peerTypes?: Api.TypeAttachMenuPeerType[]; icons: Api.TypeAttachMenuBotIcon[]; }> { - // flags: undefined; + // flags: Api.Type; inactive?: true; hasSettings?: true; requestWriteAccess?: true; @@ -8875,8 +9971,11 @@ namespace Api { shortName: string; peerTypes?: Api.TypeAttachMenuPeerType[]; icons: Api.TypeAttachMenuBotIcon[]; - }; - export class AttachMenuBotsNotModified extends VirtualClass {}; + static fromReader(reader: Reader): AttachMenuBot; + } + export class AttachMenuBotsNotModified extends VirtualClass { + static fromReader(reader: Reader): AttachMenuBotsNotModified; + } export class AttachMenuBots extends VirtualClass<{ hash: long; bots: Api.TypeAttachMenuBot[]; @@ -8885,131 +9984,165 @@ namespace Api { hash: long; bots: Api.TypeAttachMenuBot[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): AttachMenuBots; + } export class AttachMenuBotsBot extends VirtualClass<{ bot: Api.TypeAttachMenuBot; users: Api.TypeUser[]; }> { bot: Api.TypeAttachMenuBot; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): AttachMenuBotsBot; + } export class WebViewResultUrl extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; fullsize?: true; fullscreen?: true; queryId?: long; url: string; }> { - // flags: undefined; + // flags: Api.Type; fullsize?: true; fullscreen?: true; queryId?: long; url: string; - }; + static fromReader(reader: Reader): WebViewResultUrl; + } export class WebViewMessageSent extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; msgId?: Api.TypeInputBotInlineMessageID; } | void> { - // flags: undefined; + // flags: Api.Type; msgId?: Api.TypeInputBotInlineMessageID; - }; - export class BotMenuButtonDefault extends VirtualClass {}; - export class BotMenuButtonCommands extends VirtualClass {}; + static fromReader(reader: Reader): WebViewMessageSent; + } + export class BotMenuButtonDefault extends VirtualClass { + static fromReader(reader: Reader): BotMenuButtonDefault; + } + export class BotMenuButtonCommands extends VirtualClass { + static fromReader(reader: Reader): BotMenuButtonCommands; + } export class BotMenuButton extends VirtualClass<{ text: string; url: string; }> { text: string; url: string; - }; - export class NotificationSoundDefault extends VirtualClass {}; - export class NotificationSoundNone extends VirtualClass {}; + static fromReader(reader: Reader): BotMenuButton; + } + export class NotificationSoundDefault extends VirtualClass { + static fromReader(reader: Reader): NotificationSoundDefault; + } + export class NotificationSoundNone extends VirtualClass { + static fromReader(reader: Reader): NotificationSoundNone; + } export class NotificationSoundLocal extends VirtualClass<{ title: string; data: string; }> { title: string; data: string; - }; + static fromReader(reader: Reader): NotificationSoundLocal; + } export class NotificationSoundRingtone extends VirtualClass<{ id: long; }> { id: long; - }; - export class AttachMenuPeerTypeSameBotPM extends VirtualClass {}; - export class AttachMenuPeerTypeBotPM extends VirtualClass {}; - export class AttachMenuPeerTypePM extends VirtualClass {}; - export class AttachMenuPeerTypeChat extends VirtualClass {}; - export class AttachMenuPeerTypeBroadcast extends VirtualClass {}; + static fromReader(reader: Reader): NotificationSoundRingtone; + } + export class AttachMenuPeerTypeSameBotPM extends VirtualClass { + static fromReader(reader: Reader): AttachMenuPeerTypeSameBotPM; + } + export class AttachMenuPeerTypeBotPM extends VirtualClass { + static fromReader(reader: Reader): AttachMenuPeerTypeBotPM; + } + export class AttachMenuPeerTypePM extends VirtualClass { + static fromReader(reader: Reader): AttachMenuPeerTypePM; + } + export class AttachMenuPeerTypeChat extends VirtualClass { + static fromReader(reader: Reader): AttachMenuPeerTypeChat; + } + export class AttachMenuPeerTypeBroadcast extends VirtualClass { + static fromReader(reader: Reader): AttachMenuPeerTypeBroadcast; + } export class InputInvoiceMessage extends VirtualClass<{ peer: Api.TypeInputPeer; msgId: int; }> { peer: Api.TypeInputPeer; msgId: int; - }; + static fromReader(reader: Reader): InputInvoiceMessage; + } export class InputInvoiceSlug extends VirtualClass<{ slug: string; }> { slug: string; - }; + static fromReader(reader: Reader): InputInvoiceSlug; + } export class InputInvoicePremiumGiftCode extends VirtualClass<{ purpose: Api.TypeInputStorePaymentPurpose; option: Api.TypePremiumGiftCodeOption; }> { purpose: Api.TypeInputStorePaymentPurpose; option: Api.TypePremiumGiftCodeOption; - }; + static fromReader(reader: Reader): InputInvoicePremiumGiftCode; + } export class InputInvoiceStars extends VirtualClass<{ purpose: Api.TypeInputStorePaymentPurpose; }> { purpose: Api.TypeInputStorePaymentPurpose; - }; + static fromReader(reader: Reader): InputInvoiceStars; + } export class InputInvoiceChatInviteSubscription extends VirtualClass<{ hash: string; }> { hash: string; - }; + static fromReader(reader: Reader): InputInvoiceChatInviteSubscription; + } export class InputInvoiceStarGift extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; hideName?: true; includeUpgrade?: true; userId: Api.TypeInputUser; giftId: long; message?: Api.TypeTextWithEntities; }> { - // flags: undefined; + // flags: Api.Type; hideName?: true; includeUpgrade?: true; userId: Api.TypeInputUser; giftId: long; message?: Api.TypeTextWithEntities; - }; + static fromReader(reader: Reader): InputInvoiceStarGift; + } export class InputInvoiceStarGiftUpgrade extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; keepOriginalDetails?: true; msgId: int; }> { - // flags: undefined; + // flags: Api.Type; keepOriginalDetails?: true; msgId: int; - }; + static fromReader(reader: Reader): InputInvoiceStarGiftUpgrade; + } export class InputInvoiceStarGiftTransfer extends VirtualClass<{ msgId: int; toId: Api.TypeInputUser; }> { msgId: int; toId: Api.TypeInputUser; - }; + static fromReader(reader: Reader): InputInvoiceStarGiftTransfer; + } export class InputStorePaymentPremiumSubscription extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; restore?: true; upgrade?: true; } | void> { - // flags: undefined; + // flags: Api.Type; restore?: true; upgrade?: true; - }; + static fromReader(reader: Reader): InputStorePaymentPremiumSubscription; + } export class InputStorePaymentGiftPremium extends VirtualClass<{ userId: Api.TypeInputUser; currency: string; @@ -9018,24 +10151,26 @@ namespace Api { userId: Api.TypeInputUser; currency: string; amount: long; - }; + static fromReader(reader: Reader): InputStorePaymentGiftPremium; + } export class InputStorePaymentPremiumGiftCode extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; users: Api.TypeInputUser[]; boostPeer?: Api.TypeInputPeer; currency: string; amount: long; message?: Api.TypeTextWithEntities; }> { - // flags: undefined; + // flags: Api.Type; users: Api.TypeInputUser[]; boostPeer?: Api.TypeInputPeer; currency: string; amount: long; message?: Api.TypeTextWithEntities; - }; + static fromReader(reader: Reader): InputStorePaymentPremiumGiftCode; + } export class InputStorePaymentPremiumGiveaway extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; onlyNewSubscribers?: true; winnersAreVisible?: true; boostPeer: Api.TypeInputPeer; @@ -9047,7 +10182,7 @@ namespace Api { currency: string; amount: long; }> { - // flags: undefined; + // flags: Api.Type; onlyNewSubscribers?: true; winnersAreVisible?: true; boostPeer: Api.TypeInputPeer; @@ -9058,7 +10193,8 @@ namespace Api { untilDate: int; currency: string; amount: long; - }; + static fromReader(reader: Reader): InputStorePaymentPremiumGiveaway; + } export class InputStorePaymentStarsTopup extends VirtualClass<{ stars: long; currency: string; @@ -9067,7 +10203,8 @@ namespace Api { stars: long; currency: string; amount: long; - }; + static fromReader(reader: Reader): InputStorePaymentStarsTopup; + } export class InputStorePaymentStarsGift extends VirtualClass<{ userId: Api.TypeInputUser; stars: long; @@ -9078,9 +10215,10 @@ namespace Api { stars: long; currency: string; amount: long; - }; + static fromReader(reader: Reader): InputStorePaymentStarsGift; + } export class InputStorePaymentStarsGiveaway extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; onlyNewSubscribers?: true; winnersAreVisible?: true; stars: long; @@ -9094,7 +10232,7 @@ namespace Api { amount: long; users: int; }> { - // flags: undefined; + // flags: Api.Type; onlyNewSubscribers?: true; winnersAreVisible?: true; stars: long; @@ -9107,93 +10245,118 @@ namespace Api { currency: string; amount: long; users: int; - }; + static fromReader(reader: Reader): InputStorePaymentStarsGiveaway; + } export class PremiumGiftOption extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; months: int; currency: string; amount: long; botUrl: string; storeProduct?: string; }> { - // flags: undefined; + // flags: Api.Type; months: int; currency: string; amount: long; botUrl: string; storeProduct?: string; - }; + static fromReader(reader: Reader): PremiumGiftOption; + } export class PaymentFormMethod extends VirtualClass<{ url: string; title: string; }> { url: string; title: string; - }; - export class EmojiStatusEmpty extends VirtualClass {}; + static fromReader(reader: Reader): PaymentFormMethod; + } + export class EmojiStatusEmpty extends VirtualClass { + static fromReader(reader: Reader): EmojiStatusEmpty; + } export class EmojiStatus extends VirtualClass<{ documentId: long; }> { documentId: long; - }; + static fromReader(reader: Reader): EmojiStatus; + } export class EmojiStatusUntil extends VirtualClass<{ documentId: long; until: int; }> { documentId: long; until: int; - }; - export class ReactionEmpty extends VirtualClass {}; + static fromReader(reader: Reader): EmojiStatusUntil; + } + export class ReactionEmpty extends VirtualClass { + static fromReader(reader: Reader): ReactionEmpty; + } export class ReactionEmoji extends VirtualClass<{ emoticon: string; }> { emoticon: string; - }; + static fromReader(reader: Reader): ReactionEmoji; + } export class ReactionCustomEmoji extends VirtualClass<{ documentId: long; }> { documentId: long; - }; - export class ReactionPaid extends VirtualClass {}; - export class ChatReactionsNone extends VirtualClass {}; + static fromReader(reader: Reader): ReactionCustomEmoji; + } + export class ReactionPaid extends VirtualClass { + static fromReader(reader: Reader): ReactionPaid; + } + export class ChatReactionsNone extends VirtualClass { + static fromReader(reader: Reader): ChatReactionsNone; + } export class ChatReactionsAll extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; allowCustom?: true; } | void> { - // flags: undefined; + // flags: Api.Type; allowCustom?: true; - }; + static fromReader(reader: Reader): ChatReactionsAll; + } export class ChatReactionsSome extends VirtualClass<{ reactions: Api.TypeReaction[]; }> { reactions: Api.TypeReaction[]; - }; + static fromReader(reader: Reader): ChatReactionsSome; + } export class EmailVerifyPurposeLoginSetup extends VirtualClass<{ phoneNumber: string; phoneCodeHash: string; }> { phoneNumber: string; phoneCodeHash: string; - }; - export class EmailVerifyPurposeLoginChange extends VirtualClass {}; - export class EmailVerifyPurposePassport extends VirtualClass {}; + static fromReader(reader: Reader): EmailVerifyPurposeLoginSetup; + } + export class EmailVerifyPurposeLoginChange extends VirtualClass { + static fromReader(reader: Reader): EmailVerifyPurposeLoginChange; + } + export class EmailVerifyPurposePassport extends VirtualClass { + static fromReader(reader: Reader): EmailVerifyPurposePassport; + } export class EmailVerificationCode extends VirtualClass<{ code: string; }> { code: string; - }; + static fromReader(reader: Reader): EmailVerificationCode; + } export class EmailVerificationGoogle extends VirtualClass<{ token: string; }> { token: string; - }; + static fromReader(reader: Reader): EmailVerificationGoogle; + } export class EmailVerificationApple extends VirtualClass<{ token: string; }> { token: string; - }; + static fromReader(reader: Reader): EmailVerificationApple; + } export class PremiumSubscriptionOption extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; current?: true; canPurchaseUpgrade?: true; transaction?: string; @@ -9203,7 +10366,7 @@ namespace Api { botUrl: string; storeProduct?: string; }> { - // flags: undefined; + // flags: Api.Type; current?: true; canPurchaseUpgrade?: true; transaction?: string; @@ -9212,59 +10375,66 @@ namespace Api { amount: long; botUrl: string; storeProduct?: string; - }; + static fromReader(reader: Reader): PremiumSubscriptionOption; + } export class SendAsPeer extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; premiumRequired?: true; peer: Api.TypePeer; }> { - // flags: undefined; + // flags: Api.Type; premiumRequired?: true; peer: Api.TypePeer; - }; + static fromReader(reader: Reader): SendAsPeer; + } export class MessageExtendedMediaPreview extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; w?: int; h?: int; thumb?: Api.TypePhotoSize; videoDuration?: int; } | void> { - // flags: undefined; + // flags: Api.Type; w?: int; h?: int; thumb?: Api.TypePhotoSize; videoDuration?: int; - }; + static fromReader(reader: Reader): MessageExtendedMediaPreview; + } export class MessageExtendedMedia extends VirtualClass<{ media: Api.TypeMessageMedia; }> { media: Api.TypeMessageMedia; - }; + static fromReader(reader: Reader): MessageExtendedMedia; + } export class StickerKeyword extends VirtualClass<{ documentId: long; keyword: string[]; }> { documentId: long; keyword: string[]; - }; + static fromReader(reader: Reader): StickerKeyword; + } export class Username extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; editable?: true; active?: true; username: string; }> { - // flags: undefined; + // flags: Api.Type; editable?: true; active?: true; username: string; - }; + static fromReader(reader: Reader): Username; + } export class ForumTopicDeleted extends VirtualClass<{ id: int; }> { id: int; - }; + static fromReader(reader: Reader): ForumTopicDeleted; + } export class ForumTopic extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; my?: true; closed?: true; pinned?: true; @@ -9285,7 +10455,7 @@ namespace Api { notifySettings: Api.TypePeerNotifySettings; draft?: Api.TypeDraftMessage; }> { - // flags: undefined; + // flags: Api.Type; my?: true; closed?: true; pinned?: true; @@ -9305,30 +10475,34 @@ namespace Api { fromId: Api.TypePeer; notifySettings: Api.TypePeerNotifySettings; draft?: Api.TypeDraftMessage; - }; + static fromReader(reader: Reader): ForumTopic; + } export class DefaultHistoryTTL extends VirtualClass<{ period: int; }> { period: int; - }; + static fromReader(reader: Reader): DefaultHistoryTTL; + } export class ExportedContactToken extends VirtualClass<{ url: string; expires: int; }> { url: string; expires: int; - }; + static fromReader(reader: Reader): ExportedContactToken; + } export class RequestPeerTypeUser extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; bot?: Bool; premium?: Bool; } | void> { - // flags: undefined; + // flags: Api.Type; bot?: Bool; premium?: Bool; - }; + static fromReader(reader: Reader): RequestPeerTypeUser; + } export class RequestPeerTypeChat extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; creator?: true; botParticipant?: true; hasUsername?: Bool; @@ -9336,35 +10510,40 @@ namespace Api { userAdminRights?: Api.TypeChatAdminRights; botAdminRights?: Api.TypeChatAdminRights; } | void> { - // flags: undefined; + // flags: Api.Type; creator?: true; botParticipant?: true; hasUsername?: Bool; forum?: Bool; userAdminRights?: Api.TypeChatAdminRights; botAdminRights?: Api.TypeChatAdminRights; - }; + static fromReader(reader: Reader): RequestPeerTypeChat; + } export class RequestPeerTypeBroadcast extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; creator?: true; hasUsername?: Bool; userAdminRights?: Api.TypeChatAdminRights; botAdminRights?: Api.TypeChatAdminRights; } | void> { - // flags: undefined; + // flags: Api.Type; creator?: true; hasUsername?: Bool; userAdminRights?: Api.TypeChatAdminRights; botAdminRights?: Api.TypeChatAdminRights; - }; - export class EmojiListNotModified extends VirtualClass {}; + static fromReader(reader: Reader): RequestPeerTypeBroadcast; + } + export class EmojiListNotModified extends VirtualClass { + static fromReader(reader: Reader): EmojiListNotModified; + } export class EmojiList extends VirtualClass<{ hash: long; documentId: long[]; }> { hash: long; documentId: long[]; - }; + static fromReader(reader: Reader): EmojiList; + } export class EmojiGroup extends VirtualClass<{ title: string; iconEmojiId: long; @@ -9373,7 +10552,8 @@ namespace Api { title: string; iconEmojiId: long; emoticons: string[]; - }; + static fromReader(reader: Reader): EmojiGroup; + } export class EmojiGroupGreeting extends VirtualClass<{ title: string; iconEmojiId: long; @@ -9382,56 +10562,65 @@ namespace Api { title: string; iconEmojiId: long; emoticons: string[]; - }; + static fromReader(reader: Reader): EmojiGroupGreeting; + } export class EmojiGroupPremium extends VirtualClass<{ title: string; iconEmojiId: long; }> { title: string; iconEmojiId: long; - }; + static fromReader(reader: Reader): EmojiGroupPremium; + } export class TextWithEntities extends VirtualClass<{ text: string; entities: Api.TypeMessageEntity[]; }> { text: string; entities: Api.TypeMessageEntity[]; - }; + static fromReader(reader: Reader): TextWithEntities; + } export class AutoSaveSettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; photos?: true; videos?: true; videoMaxSize?: long; } | void> { - // flags: undefined; + // flags: Api.Type; photos?: true; videos?: true; videoMaxSize?: long; - }; + static fromReader(reader: Reader): AutoSaveSettings; + } export class AutoSaveException extends VirtualClass<{ peer: Api.TypePeer; settings: Api.TypeAutoSaveSettings; }> { peer: Api.TypePeer; settings: Api.TypeAutoSaveSettings; - }; + static fromReader(reader: Reader): AutoSaveException; + } export class InputBotAppID extends VirtualClass<{ id: long; accessHash: long; }> { id: long; accessHash: long; - }; + static fromReader(reader: Reader): InputBotAppID; + } export class InputBotAppShortName extends VirtualClass<{ botId: Api.TypeInputUser; shortName: string; }> { botId: Api.TypeInputUser; shortName: string; - }; - export class BotAppNotModified extends VirtualClass {}; + static fromReader(reader: Reader): InputBotAppShortName; + } + export class BotAppNotModified extends VirtualClass { + static fromReader(reader: Reader): BotAppNotModified; + } export class BotApp extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; id: long; accessHash: long; shortName: string; @@ -9441,7 +10630,7 @@ namespace Api { document?: Api.TypeDocument; hash: long; }> { - // flags: undefined; + // flags: Api.Type; id: long; accessHash: long; shortName: string; @@ -9450,37 +10639,42 @@ namespace Api { photo: Api.TypePhoto; document?: Api.TypeDocument; hash: long; - }; + static fromReader(reader: Reader): BotApp; + } export class InlineBotWebView extends VirtualClass<{ text: string; url: string; }> { text: string; url: string; - }; + static fromReader(reader: Reader): InlineBotWebView; + } export class ReadParticipantDate extends VirtualClass<{ userId: long; date: int; }> { userId: long; date: int; - }; + static fromReader(reader: Reader): ReadParticipantDate; + } export class InputChatlistDialogFilter extends VirtualClass<{ filterId: int; }> { filterId: int; - }; + static fromReader(reader: Reader): InputChatlistDialogFilter; + } export class ExportedChatlistInvite extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; title: string; url: string; peers: Api.TypePeer[]; }> { - // flags: undefined; + // flags: Api.Type; title: string; url: string; peers: Api.TypePeer[]; - }; + static fromReader(reader: Reader): ExportedChatlistInvite; + } export class MessagePeerVote extends VirtualClass<{ peer: Api.TypePeer; option: bytes; @@ -9489,14 +10683,16 @@ namespace Api { peer: Api.TypePeer; option: bytes; date: int; - }; + static fromReader(reader: Reader): MessagePeerVote; + } export class MessagePeerVoteInputOption extends VirtualClass<{ peer: Api.TypePeer; date: int; }> { peer: Api.TypePeer; date: int; - }; + static fromReader(reader: Reader): MessagePeerVoteInputOption; + } export class MessagePeerVoteMultiple extends VirtualClass<{ peer: Api.TypePeer; options: bytes[]; @@ -9505,9 +10701,10 @@ namespace Api { peer: Api.TypePeer; options: bytes[]; date: int; - }; + static fromReader(reader: Reader): MessagePeerVoteMultiple; + } export class StoryViews extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; hasViewers?: true; viewsCount: int; forwardsCount?: int; @@ -9515,34 +10712,37 @@ namespace Api { reactionsCount?: int; recentViewers?: long[]; }> { - // flags: undefined; + // flags: Api.Type; hasViewers?: true; viewsCount: int; forwardsCount?: int; reactions?: Api.TypeReactionCount[]; reactionsCount?: int; recentViewers?: long[]; - }; + static fromReader(reader: Reader): StoryViews; + } export class StoryItemDeleted extends VirtualClass<{ id: int; }> { id: int; - }; + static fromReader(reader: Reader): StoryItemDeleted; + } export class StoryItemSkipped extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; closeFriends?: true; id: int; date: int; expireDate: int; }> { - // flags: undefined; + // flags: Api.Type; closeFriends?: true; id: int; date: int; expireDate: int; - }; + static fromReader(reader: Reader): StoryItemSkipped; + } export class StoryItem extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; pinned?: true; public?: true; closeFriends?: true; @@ -9565,7 +10765,7 @@ namespace Api { views?: Api.TypeStoryViews; sentReaction?: Api.TypeReaction; }> { - // flags: undefined; + // flags: Api.Type; pinned?: true; public?: true; closeFriends?: true; @@ -9587,48 +10787,52 @@ namespace Api { privacy?: Api.TypePrivacyRule[]; views?: Api.TypeStoryViews; sentReaction?: Api.TypeReaction; - }; + static fromReader(reader: Reader): StoryItem; + } export class StoryView extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; blocked?: true; blockedMyStoriesFrom?: true; userId: long; date: int; reaction?: Api.TypeReaction; }> { - // flags: undefined; + // flags: Api.Type; blocked?: true; blockedMyStoriesFrom?: true; userId: long; date: int; reaction?: Api.TypeReaction; - }; + static fromReader(reader: Reader): StoryView; + } export class StoryViewPublicForward extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; blocked?: true; blockedMyStoriesFrom?: true; message: Api.TypeMessage; }> { - // flags: undefined; + // flags: Api.Type; blocked?: true; blockedMyStoriesFrom?: true; message: Api.TypeMessage; - }; + static fromReader(reader: Reader): StoryViewPublicForward; + } export class StoryViewPublicRepost extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; blocked?: true; blockedMyStoriesFrom?: true; peerId: Api.TypePeer; story: Api.TypeStoryItem; }> { - // flags: undefined; + // flags: Api.Type; blocked?: true; blockedMyStoriesFrom?: true; peerId: Api.TypePeer; story: Api.TypeStoryItem; - }; + static fromReader(reader: Reader): StoryViewPublicRepost; + } export class InputReplyToMessage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; replyToMsgId: int; topMsgId?: int; replyToPeerId?: Api.TypeInputPeer; @@ -9636,37 +10840,41 @@ namespace Api { quoteEntities?: Api.TypeMessageEntity[]; quoteOffset?: int; }> { - // flags: undefined; + // flags: Api.Type; replyToMsgId: int; topMsgId?: int; replyToPeerId?: Api.TypeInputPeer; quoteText?: string; quoteEntities?: Api.TypeMessageEntity[]; quoteOffset?: int; - }; + static fromReader(reader: Reader): InputReplyToMessage; + } export class InputReplyToStory extends VirtualClass<{ peer: Api.TypeInputPeer; storyId: int; }> { peer: Api.TypeInputPeer; storyId: int; - }; + static fromReader(reader: Reader): InputReplyToStory; + } export class ExportedStoryLink extends VirtualClass<{ link: string; }> { link: string; - }; + static fromReader(reader: Reader): ExportedStoryLink; + } export class StoriesStealthMode extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; activeUntilDate?: int; cooldownUntilDate?: int; } | void> { - // flags: undefined; + // flags: Api.Type; activeUntilDate?: int; cooldownUntilDate?: int; - }; + static fromReader(reader: Reader): StoriesStealthMode; + } export class MediaAreaCoordinates extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; x: double; y: double; w: double; @@ -9674,14 +10882,15 @@ namespace Api { rotation: double; radius?: double; }> { - // flags: undefined; + // flags: Api.Type; x: double; y: double; w: double; h: double; rotation: double; radius?: double; - }; + static fromReader(reader: Reader): MediaAreaCoordinates; + } export class MediaAreaVenue extends VirtualClass<{ coordinates: Api.TypeMediaAreaCoordinates; geo: Api.TypeGeoPoint; @@ -9698,7 +10907,8 @@ namespace Api { provider: string; venueId: string; venueType: string; - }; + static fromReader(reader: Reader): MediaAreaVenue; + } export class InputMediaAreaVenue extends VirtualClass<{ coordinates: Api.TypeMediaAreaCoordinates; queryId: long; @@ -9707,31 +10917,34 @@ namespace Api { coordinates: Api.TypeMediaAreaCoordinates; queryId: long; resultId: string; - }; + static fromReader(reader: Reader): InputMediaAreaVenue; + } export class MediaAreaGeoPoint extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; coordinates: Api.TypeMediaAreaCoordinates; geo: Api.TypeGeoPoint; address?: Api.TypeGeoPointAddress; }> { - // flags: undefined; + // flags: Api.Type; coordinates: Api.TypeMediaAreaCoordinates; geo: Api.TypeGeoPoint; address?: Api.TypeGeoPointAddress; - }; + static fromReader(reader: Reader): MediaAreaGeoPoint; + } export class MediaAreaSuggestedReaction extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; dark?: true; flipped?: true; coordinates: Api.TypeMediaAreaCoordinates; reaction: Api.TypeReaction; }> { - // flags: undefined; + // flags: Api.Type; dark?: true; flipped?: true; coordinates: Api.TypeMediaAreaCoordinates; reaction: Api.TypeReaction; - }; + static fromReader(reader: Reader): MediaAreaSuggestedReaction; + } export class MediaAreaChannelPost extends VirtualClass<{ coordinates: Api.TypeMediaAreaCoordinates; channelId: long; @@ -9740,7 +10953,8 @@ namespace Api { coordinates: Api.TypeMediaAreaCoordinates; channelId: long; msgId: int; - }; + static fromReader(reader: Reader): MediaAreaChannelPost; + } export class InputMediaAreaChannelPost extends VirtualClass<{ coordinates: Api.TypeMediaAreaCoordinates; channel: Api.TypeInputChannel; @@ -9749,14 +10963,16 @@ namespace Api { coordinates: Api.TypeMediaAreaCoordinates; channel: Api.TypeInputChannel; msgId: int; - }; + static fromReader(reader: Reader): InputMediaAreaChannelPost; + } export class MediaAreaUrl extends VirtualClass<{ coordinates: Api.TypeMediaAreaCoordinates; url: string; }> { coordinates: Api.TypeMediaAreaCoordinates; url: string; - }; + static fromReader(reader: Reader): MediaAreaUrl; + } export class MediaAreaWeather extends VirtualClass<{ coordinates: Api.TypeMediaAreaCoordinates; emoji: string; @@ -9767,27 +10983,30 @@ namespace Api { emoji: string; temperatureC: double; color: int; - }; + static fromReader(reader: Reader): MediaAreaWeather; + } export class MediaAreaStarGift extends VirtualClass<{ coordinates: Api.TypeMediaAreaCoordinates; slug: string; }> { coordinates: Api.TypeMediaAreaCoordinates; slug: string; - }; + static fromReader(reader: Reader): MediaAreaStarGift; + } export class PeerStories extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; maxReadId?: int; stories: Api.TypeStoryItem[]; }> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; maxReadId?: int; stories: Api.TypeStoryItem[]; - }; + static fromReader(reader: Reader): PeerStories; + } export class PremiumGiftCodeOption extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; users: int; months: int; storeProduct?: string; @@ -9795,14 +11014,15 @@ namespace Api { currency: string; amount: long; }> { - // flags: undefined; + // flags: Api.Type; users: int; months: int; storeProduct?: string; storeQuantity?: int; currency: string; amount: long; - }; + static fromReader(reader: Reader): PremiumGiftCodeOption; + } export class PrepaidGiveaway extends VirtualClass<{ id: long; months: int; @@ -9813,7 +11033,8 @@ namespace Api { months: int; quantity: int; date: int; - }; + static fromReader(reader: Reader): PrepaidGiveaway; + } export class PrepaidStarsGiveaway extends VirtualClass<{ id: long; stars: long; @@ -9826,9 +11047,10 @@ namespace Api { quantity: int; boosts: int; date: int; - }; + static fromReader(reader: Reader): PrepaidStarsGiveaway; + } export class Boost extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; gift?: true; giveaway?: true; unclaimed?: true; @@ -9841,7 +11063,7 @@ namespace Api { multiplier?: int; stars?: long; }> { - // flags: undefined; + // flags: Api.Type; gift?: true; giveaway?: true; unclaimed?: true; @@ -9853,35 +11075,38 @@ namespace Api { usedGiftSlug?: string; multiplier?: int; stars?: long; - }; + static fromReader(reader: Reader): Boost; + } export class MyBoost extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; slot: int; peer?: Api.TypePeer; date: int; expires: int; cooldownUntilDate?: int; }> { - // flags: undefined; + // flags: Api.Type; slot: int; peer?: Api.TypePeer; date: int; expires: int; cooldownUntilDate?: int; - }; + static fromReader(reader: Reader): MyBoost; + } export class StoryFwdHeader extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; modified?: true; from?: Api.TypePeer; fromName?: string; storyId?: int; } | void> { - // flags: undefined; + // flags: Api.Type; modified?: true; from?: Api.TypePeer; fromName?: string; storyId?: int; - }; + static fromReader(reader: Reader): StoryFwdHeader; + } export class PostInteractionCountersMessage extends VirtualClass<{ msgId: int; views: int; @@ -9892,7 +11117,8 @@ namespace Api { views: int; forwards: int; reactions: int; - }; + static fromReader(reader: Reader): PostInteractionCountersMessage; + } export class PostInteractionCountersStory extends VirtualClass<{ storyId: int; views: int; @@ -9903,28 +11129,32 @@ namespace Api { views: int; forwards: int; reactions: int; - }; + static fromReader(reader: Reader): PostInteractionCountersStory; + } export class PublicForwardMessage extends VirtualClass<{ message: Api.TypeMessage; }> { message: Api.TypeMessage; - }; + static fromReader(reader: Reader): PublicForwardMessage; + } export class PublicForwardStory extends VirtualClass<{ peer: Api.TypePeer; story: Api.TypeStoryItem; }> { peer: Api.TypePeer; story: Api.TypeStoryItem; - }; + static fromReader(reader: Reader): PublicForwardStory; + } export class PeerColor extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; color?: int; backgroundEmojiId?: long; } | void> { - // flags: undefined; + // flags: Api.Type; color?: int; backgroundEmojiId?: long; - }; + static fromReader(reader: Reader): PeerColor; + } export class StoryReaction extends VirtualClass<{ peerId: Api.TypePeer; date: int; @@ -9933,46 +11163,52 @@ namespace Api { peerId: Api.TypePeer; date: int; reaction: Api.TypeReaction; - }; + static fromReader(reader: Reader): StoryReaction; + } export class StoryReactionPublicForward extends VirtualClass<{ message: Api.TypeMessage; }> { message: Api.TypeMessage; - }; + static fromReader(reader: Reader): StoryReactionPublicForward; + } export class StoryReactionPublicRepost extends VirtualClass<{ peerId: Api.TypePeer; story: Api.TypeStoryItem; }> { peerId: Api.TypePeer; story: Api.TypeStoryItem; - }; + static fromReader(reader: Reader): StoryReactionPublicRepost; + } export class SavedDialog extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; pinned?: true; peer: Api.TypePeer; topMessage: int; }> { - // flags: undefined; + // flags: Api.Type; pinned?: true; peer: Api.TypePeer; topMessage: int; - }; + static fromReader(reader: Reader): SavedDialog; + } export class SavedReactionTag extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; reaction: Api.TypeReaction; title?: string; count: int; }> { - // flags: undefined; + // flags: Api.Type; reaction: Api.TypeReaction; title?: string; count: int; - }; + static fromReader(reader: Reader): SavedReactionTag; + } export class OutboxReadDate extends VirtualClass<{ date: int; }> { date: int; - }; + static fromReader(reader: Reader): OutboxReadDate; + } export class SmsJob extends VirtualClass<{ jobId: string; phoneNumber: string; @@ -9981,36 +11217,40 @@ namespace Api { jobId: string; phoneNumber: string; text: string; - }; + static fromReader(reader: Reader): SmsJob; + } export class BusinessWeeklyOpen extends VirtualClass<{ startMinute: int; endMinute: int; }> { startMinute: int; endMinute: int; - }; + static fromReader(reader: Reader): BusinessWeeklyOpen; + } export class BusinessWorkHours extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; openNow?: true; timezoneId: string; weeklyOpen: Api.TypeBusinessWeeklyOpen[]; }> { - // flags: undefined; + // flags: Api.Type; openNow?: true; timezoneId: string; weeklyOpen: Api.TypeBusinessWeeklyOpen[]; - }; + static fromReader(reader: Reader): BusinessWorkHours; + } export class BusinessLocation extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; geoPoint?: Api.TypeGeoPoint; address: string; }> { - // flags: undefined; + // flags: Api.Type; geoPoint?: Api.TypeGeoPoint; address: string; - }; + static fromReader(reader: Reader): BusinessLocation; + } export class InputBusinessRecipients extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; existingChats?: true; newChats?: true; contacts?: true; @@ -10018,16 +11258,17 @@ namespace Api { excludeSelected?: true; users?: Api.TypeInputUser[]; } | void> { - // flags: undefined; + // flags: Api.Type; existingChats?: true; newChats?: true; contacts?: true; nonContacts?: true; excludeSelected?: true; users?: Api.TypeInputUser[]; - }; + static fromReader(reader: Reader): InputBusinessRecipients; + } export class BusinessRecipients extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; existingChats?: true; newChats?: true; contacts?: true; @@ -10035,23 +11276,29 @@ namespace Api { excludeSelected?: true; users?: long[]; } | void> { - // flags: undefined; + // flags: Api.Type; existingChats?: true; newChats?: true; contacts?: true; nonContacts?: true; excludeSelected?: true; users?: long[]; - }; - export class BusinessAwayMessageScheduleAlways extends VirtualClass {}; - export class BusinessAwayMessageScheduleOutsideWorkHours extends VirtualClass {}; + static fromReader(reader: Reader): BusinessRecipients; + } + export class BusinessAwayMessageScheduleAlways extends VirtualClass { + static fromReader(reader: Reader): BusinessAwayMessageScheduleAlways; + } + export class BusinessAwayMessageScheduleOutsideWorkHours extends VirtualClass { + static fromReader(reader: Reader): BusinessAwayMessageScheduleOutsideWorkHours; + } export class BusinessAwayMessageScheduleCustom extends VirtualClass<{ startDate: int; endDate: int; }> { startDate: int; endDate: int; - }; + static fromReader(reader: Reader): BusinessAwayMessageScheduleCustom; + } export class InputBusinessGreetingMessage extends VirtualClass<{ shortcutId: int; recipients: Api.TypeInputBusinessRecipients; @@ -10060,7 +11307,8 @@ namespace Api { shortcutId: int; recipients: Api.TypeInputBusinessRecipients; noActivityDays: int; - }; + static fromReader(reader: Reader): InputBusinessGreetingMessage; + } export class BusinessGreetingMessage extends VirtualClass<{ shortcutId: int; recipients: Api.TypeBusinessRecipients; @@ -10069,33 +11317,36 @@ namespace Api { shortcutId: int; recipients: Api.TypeBusinessRecipients; noActivityDays: int; - }; + static fromReader(reader: Reader): BusinessGreetingMessage; + } export class InputBusinessAwayMessage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; offlineOnly?: true; shortcutId: int; schedule: Api.TypeBusinessAwayMessageSchedule; recipients: Api.TypeInputBusinessRecipients; }> { - // flags: undefined; + // flags: Api.Type; offlineOnly?: true; shortcutId: int; schedule: Api.TypeBusinessAwayMessageSchedule; recipients: Api.TypeInputBusinessRecipients; - }; + static fromReader(reader: Reader): InputBusinessAwayMessage; + } export class BusinessAwayMessage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; offlineOnly?: true; shortcutId: int; schedule: Api.TypeBusinessAwayMessageSchedule; recipients: Api.TypeBusinessRecipients; }> { - // flags: undefined; + // flags: Api.Type; offlineOnly?: true; shortcutId: int; schedule: Api.TypeBusinessAwayMessageSchedule; recipients: Api.TypeBusinessRecipients; - }; + static fromReader(reader: Reader): BusinessAwayMessage; + } export class Timezone extends VirtualClass<{ id: string; name: string; @@ -10104,7 +11355,8 @@ namespace Api { id: string; name: string; utcOffset: int; - }; + static fromReader(reader: Reader): Timezone; + } export class QuickReply extends VirtualClass<{ shortcutId: int; shortcut: string; @@ -10115,41 +11367,46 @@ namespace Api { shortcut: string; topMessage: int; count: int; - }; + static fromReader(reader: Reader): QuickReply; + } export class InputQuickReplyShortcut extends VirtualClass<{ shortcut: string; }> { shortcut: string; - }; + static fromReader(reader: Reader): InputQuickReplyShortcut; + } export class InputQuickReplyShortcutId extends VirtualClass<{ shortcutId: int; }> { shortcutId: int; - }; + static fromReader(reader: Reader): InputQuickReplyShortcutId; + } export class ConnectedBot extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; canReply?: true; botId: long; recipients: Api.TypeBusinessBotRecipients; }> { - // flags: undefined; + // flags: Api.Type; canReply?: true; botId: long; recipients: Api.TypeBusinessBotRecipients; - }; + static fromReader(reader: Reader): ConnectedBot; + } export class Birthday extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; day: int; month: int; year?: int; }> { - // flags: undefined; + // flags: Api.Type; day: int; month: int; year?: int; - }; + static fromReader(reader: Reader): Birthday; + } export class BotBusinessConnection extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; canReply?: true; disabled?: true; connectionId: string; @@ -10157,48 +11414,53 @@ namespace Api { dcId: int; date: int; }> { - // flags: undefined; + // flags: Api.Type; canReply?: true; disabled?: true; connectionId: string; userId: long; dcId: int; date: int; - }; + static fromReader(reader: Reader): BotBusinessConnection; + } export class InputBusinessIntro extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; title: string; description: string; sticker?: Api.TypeInputDocument; }> { - // flags: undefined; + // flags: Api.Type; title: string; description: string; sticker?: Api.TypeInputDocument; - }; + static fromReader(reader: Reader): InputBusinessIntro; + } export class BusinessIntro extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; title: string; description: string; sticker?: Api.TypeDocument; }> { - // flags: undefined; + // flags: Api.Type; title: string; description: string; sticker?: Api.TypeDocument; - }; + static fromReader(reader: Reader): BusinessIntro; + } export class InputCollectibleUsername extends VirtualClass<{ username: string; }> { username: string; - }; + static fromReader(reader: Reader): InputCollectibleUsername; + } export class InputCollectiblePhone extends VirtualClass<{ phone: string; }> { phone: string; - }; + static fromReader(reader: Reader): InputCollectiblePhone; + } export class InputBusinessBotRecipients extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; existingChats?: true; newChats?: true; contacts?: true; @@ -10207,7 +11469,7 @@ namespace Api { users?: Api.TypeInputUser[]; excludeUsers?: Api.TypeInputUser[]; } | void> { - // flags: undefined; + // flags: Api.Type; existingChats?: true; newChats?: true; contacts?: true; @@ -10215,9 +11477,10 @@ namespace Api { excludeSelected?: true; users?: Api.TypeInputUser[]; excludeUsers?: Api.TypeInputUser[]; - }; + static fromReader(reader: Reader): InputBusinessBotRecipients; + } export class BusinessBotRecipients extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; existingChats?: true; newChats?: true; contacts?: true; @@ -10226,7 +11489,7 @@ namespace Api { users?: long[]; excludeUsers?: long[]; } | void> { - // flags: undefined; + // flags: Api.Type; existingChats?: true; newChats?: true; contacts?: true; @@ -10234,97 +11497,106 @@ namespace Api { excludeSelected?: true; users?: long[]; excludeUsers?: long[]; - }; + static fromReader(reader: Reader): BusinessBotRecipients; + } export class ContactBirthday extends VirtualClass<{ contactId: long; birthday: Api.TypeBirthday; }> { contactId: long; birthday: Api.TypeBirthday; - }; + static fromReader(reader: Reader): ContactBirthday; + } export class MissingInvitee extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; premiumWouldAllowInvite?: true; premiumRequiredForPm?: true; userId: long; }> { - // flags: undefined; + // flags: Api.Type; premiumWouldAllowInvite?: true; premiumRequiredForPm?: true; userId: long; - }; + static fromReader(reader: Reader): MissingInvitee; + } export class InputBusinessChatLink extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; message: string; entities?: Api.TypeMessageEntity[]; title?: string; }> { - // flags: undefined; + // flags: Api.Type; message: string; entities?: Api.TypeMessageEntity[]; title?: string; - }; + static fromReader(reader: Reader): InputBusinessChatLink; + } export class BusinessChatLink extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; link: string; message: string; entities?: Api.TypeMessageEntity[]; title?: string; views: int; }> { - // flags: undefined; + // flags: Api.Type; link: string; message: string; entities?: Api.TypeMessageEntity[]; title?: string; views: int; - }; + static fromReader(reader: Reader): BusinessChatLink; + } export class RequestedPeerUser extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; userId: long; firstName?: string; lastName?: string; username?: string; photo?: Api.TypePhoto; }> { - // flags: undefined; + // flags: Api.Type; userId: long; firstName?: string; lastName?: string; username?: string; photo?: Api.TypePhoto; - }; + static fromReader(reader: Reader): RequestedPeerUser; + } export class RequestedPeerChat extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; chatId: long; title?: string; photo?: Api.TypePhoto; }> { - // flags: undefined; + // flags: Api.Type; chatId: long; title?: string; photo?: Api.TypePhoto; - }; + static fromReader(reader: Reader): RequestedPeerChat; + } export class RequestedPeerChannel extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; channelId: long; title?: string; username?: string; photo?: Api.TypePhoto; }> { - // flags: undefined; + // flags: Api.Type; channelId: long; title?: string; username?: string; photo?: Api.TypePhoto; - }; + static fromReader(reader: Reader): RequestedPeerChannel; + } export class SponsoredMessageReportOption extends VirtualClass<{ text: string; option: bytes; }> { text: string; option: bytes; - }; + static fromReader(reader: Reader): SponsoredMessageReportOption; + } export class BroadcastRevenueTransactionProceeds extends VirtualClass<{ amount: long; fromDate: int; @@ -10333,9 +11605,10 @@ namespace Api { amount: long; fromDate: int; toDate: int; - }; + static fromReader(reader: Reader): BroadcastRevenueTransactionProceeds; + } export class BroadcastRevenueTransactionWithdrawal extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; pending?: true; failed?: true; amount: long; @@ -10344,7 +11617,7 @@ namespace Api { transactionDate?: int; transactionUrl?: string; }> { - // flags: undefined; + // flags: Api.Type; pending?: true; failed?: true; amount: long; @@ -10352,7 +11625,8 @@ namespace Api { provider: string; transactionDate?: int; transactionUrl?: string; - }; + static fromReader(reader: Reader): BroadcastRevenueTransactionWithdrawal; + } export class BroadcastRevenueTransactionRefund extends VirtualClass<{ amount: long; date: int; @@ -10361,37 +11635,44 @@ namespace Api { amount: long; date: int; provider: string; - }; - export class ReactionNotificationsFromContacts extends VirtualClass {}; - export class ReactionNotificationsFromAll extends VirtualClass {}; + static fromReader(reader: Reader): BroadcastRevenueTransactionRefund; + } + export class ReactionNotificationsFromContacts extends VirtualClass { + static fromReader(reader: Reader): ReactionNotificationsFromContacts; + } + export class ReactionNotificationsFromAll extends VirtualClass { + static fromReader(reader: Reader): ReactionNotificationsFromAll; + } export class ReactionsNotifySettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; messagesNotifyFrom?: Api.TypeReactionNotificationsFrom; storiesNotifyFrom?: Api.TypeReactionNotificationsFrom; sound: Api.TypeNotificationSound; showPreviews: Bool; }> { - // flags: undefined; + // flags: Api.Type; messagesNotifyFrom?: Api.TypeReactionNotificationsFrom; storiesNotifyFrom?: Api.TypeReactionNotificationsFrom; sound: Api.TypeNotificationSound; showPreviews: Bool; - }; + static fromReader(reader: Reader): ReactionsNotifySettings; + } export class BroadcastRevenueBalances extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; withdrawalEnabled?: true; currentBalance: long; availableBalance: long; overallRevenue: long; }> { - // flags: undefined; + // flags: Api.Type; withdrawalEnabled?: true; currentBalance: long; availableBalance: long; overallRevenue: long; - }; + static fromReader(reader: Reader): BroadcastRevenueBalances; + } export class AvailableEffect extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; premiumRequired?: true; id: long; emoticon: string; @@ -10399,56 +11680,74 @@ namespace Api { effectStickerId: long; effectAnimationId?: long; }> { - // flags: undefined; + // flags: Api.Type; premiumRequired?: true; id: long; emoticon: string; staticIconId?: long; effectStickerId: long; effectAnimationId?: long; - }; + static fromReader(reader: Reader): AvailableEffect; + } export class FactCheck extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; needCheck?: true; country?: string; text?: Api.TypeTextWithEntities; hash: long; }> { - // flags: undefined; + // flags: Api.Type; needCheck?: true; country?: string; text?: Api.TypeTextWithEntities; hash: long; - }; - export class StarsTransactionPeerUnsupported extends VirtualClass {}; - export class StarsTransactionPeerAppStore extends VirtualClass {}; - export class StarsTransactionPeerPlayMarket extends VirtualClass {}; - export class StarsTransactionPeerPremiumBot extends VirtualClass {}; - export class StarsTransactionPeerFragment extends VirtualClass {}; + static fromReader(reader: Reader): FactCheck; + } + export class StarsTransactionPeerUnsupported extends VirtualClass { + static fromReader(reader: Reader): StarsTransactionPeerUnsupported; + } + export class StarsTransactionPeerAppStore extends VirtualClass { + static fromReader(reader: Reader): StarsTransactionPeerAppStore; + } + export class StarsTransactionPeerPlayMarket extends VirtualClass { + static fromReader(reader: Reader): StarsTransactionPeerPlayMarket; + } + export class StarsTransactionPeerPremiumBot extends VirtualClass { + static fromReader(reader: Reader): StarsTransactionPeerPremiumBot; + } + export class StarsTransactionPeerFragment extends VirtualClass { + static fromReader(reader: Reader): StarsTransactionPeerFragment; + } export class StarsTransactionPeer extends VirtualClass<{ peer: Api.TypePeer; }> { peer: Api.TypePeer; - }; - export class StarsTransactionPeerAds extends VirtualClass {}; - export class StarsTransactionPeerAPI extends VirtualClass {}; + static fromReader(reader: Reader): StarsTransactionPeer; + } + export class StarsTransactionPeerAds extends VirtualClass { + static fromReader(reader: Reader): StarsTransactionPeerAds; + } + export class StarsTransactionPeerAPI extends VirtualClass { + static fromReader(reader: Reader): StarsTransactionPeerAPI; + } export class StarsTopupOption extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; extended?: true; stars: long; storeProduct?: string; currency: string; amount: long; }> { - // flags: undefined; + // flags: Api.Type; extended?: true; stars: long; storeProduct?: string; currency: string; amount: long; - }; + static fromReader(reader: Reader): StarsTopupOption; + } export class StarsTransaction extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; refund?: true; pending?: true; failed?: true; @@ -10475,7 +11774,7 @@ namespace Api { starrefPeer?: Api.TypePeer; starrefAmount?: Api.TypeStarsAmount; }> { - // flags: undefined; + // flags: Api.Type; refund?: true; pending?: true; failed?: true; @@ -10501,82 +11800,90 @@ namespace Api { starrefCommissionPermille?: int; starrefPeer?: Api.TypePeer; starrefAmount?: Api.TypeStarsAmount; - }; + static fromReader(reader: Reader): StarsTransaction; + } export class FoundStory extends VirtualClass<{ peer: Api.TypePeer; story: Api.TypeStoryItem; }> { peer: Api.TypePeer; story: Api.TypeStoryItem; - }; + static fromReader(reader: Reader): FoundStory; + } export class GeoPointAddress extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; countryIso2: string; state?: string; city?: string; street?: string; }> { - // flags: undefined; + // flags: Api.Type; countryIso2: string; state?: string; city?: string; street?: string; - }; + static fromReader(reader: Reader): GeoPointAddress; + } export class StarsRevenueStatus extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; withdrawalEnabled?: true; currentBalance: Api.TypeStarsAmount; availableBalance: Api.TypeStarsAmount; overallRevenue: Api.TypeStarsAmount; nextWithdrawalAt?: int; }> { - // flags: undefined; + // flags: Api.Type; withdrawalEnabled?: true; currentBalance: Api.TypeStarsAmount; availableBalance: Api.TypeStarsAmount; overallRevenue: Api.TypeStarsAmount; nextWithdrawalAt?: int; - }; + static fromReader(reader: Reader): StarsRevenueStatus; + } export class InputStarsTransaction extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; refund?: true; id: string; }> { - // flags: undefined; + // flags: Api.Type; refund?: true; id: string; - }; + static fromReader(reader: Reader): InputStarsTransaction; + } export class StarsGiftOption extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; extended?: true; stars: long; storeProduct?: string; currency: string; amount: long; }> { - // flags: undefined; + // flags: Api.Type; extended?: true; stars: long; storeProduct?: string; currency: string; amount: long; - }; + static fromReader(reader: Reader): StarsGiftOption; + } export class BotPreviewMedia extends VirtualClass<{ date: int; media: Api.TypeMessageMedia; }> { date: int; media: Api.TypeMessageMedia; - }; + static fromReader(reader: Reader): BotPreviewMedia; + } export class StarsSubscriptionPricing extends VirtualClass<{ period: int; amount: long; }> { period: int; amount: long; - }; + static fromReader(reader: Reader): StarsSubscriptionPricing; + } export class StarsSubscription extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; canceled?: true; canRefulfill?: true; missingBalance?: true; @@ -10590,7 +11897,7 @@ namespace Api { photo?: Api.TypeWebDocument; invoiceSlug?: string; }> { - // flags: undefined; + // flags: Api.Type; canceled?: true; canRefulfill?: true; missingBalance?: true; @@ -10603,24 +11910,26 @@ namespace Api { title?: string; photo?: Api.TypeWebDocument; invoiceSlug?: string; - }; + static fromReader(reader: Reader): StarsSubscription; + } export class MessageReactor extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; top?: true; my?: true; anonymous?: true; peerId?: Api.TypePeer; count: int; }> { - // flags: undefined; + // flags: Api.Type; top?: true; my?: true; anonymous?: true; peerId?: Api.TypePeer; count: int; - }; + static fromReader(reader: Reader): MessageReactor; + } export class StarsGiveawayOption extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; extended?: true; default?: true; stars: long; @@ -10630,7 +11939,7 @@ namespace Api { amount: long; winners: Api.TypeStarsGiveawayWinnersOption[]; }> { - // flags: undefined; + // flags: Api.Type; extended?: true; default?: true; stars: long; @@ -10639,20 +11948,22 @@ namespace Api { currency: string; amount: long; winners: Api.TypeStarsGiveawayWinnersOption[]; - }; + static fromReader(reader: Reader): StarsGiveawayOption; + } export class StarsGiveawayWinnersOption extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; default?: true; users: int; perUserStars: long; }> { - // flags: undefined; + // flags: Api.Type; default?: true; users: int; perUserStars: long; - }; + static fromReader(reader: Reader): StarsGiveawayWinnersOption; + } export class StarGift extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; limited?: true; soldOut?: true; birthday?: true; @@ -10666,7 +11977,7 @@ namespace Api { lastSaleDate?: int; upgradeStars?: long; }> { - // flags: undefined; + // flags: Api.Type; limited?: true; soldOut?: true; birthday?: true; @@ -10679,9 +11990,10 @@ namespace Api { firstSaleDate?: int; lastSaleDate?: int; upgradeStars?: long; - }; + static fromReader(reader: Reader): StarGift; + } export class StarGiftUnique extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; id: long; title: string; slug: string; @@ -10692,7 +12004,7 @@ namespace Api { availabilityIssued: int; availabilityTotal: int; }> { - // flags: undefined; + // flags: Api.Type; id: long; title: string; slug: string; @@ -10702,9 +12014,10 @@ namespace Api { attributes: Api.TypeStarGiftAttribute[]; availabilityIssued: int; availabilityTotal: int; - }; + static fromReader(reader: Reader): StarGiftUnique; + } export class UserStarGift extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; nameHidden?: true; unsaved?: true; refunded?: true; @@ -10719,7 +12032,7 @@ namespace Api { canExportAt?: int; transferStars?: long; }> { - // flags: undefined; + // flags: Api.Type; nameHidden?: true; unsaved?: true; refunded?: true; @@ -10733,63 +12046,71 @@ namespace Api { upgradeStars?: long; canExportAt?: int; transferStars?: long; - }; + static fromReader(reader: Reader): UserStarGift; + } export class MessageReportOption extends VirtualClass<{ text: string; option: bytes; }> { text: string; option: bytes; - }; + static fromReader(reader: Reader): MessageReportOption; + } export class ReportResultChooseOption extends VirtualClass<{ title: string; options: Api.TypeMessageReportOption[]; }> { title: string; options: Api.TypeMessageReportOption[]; - }; + static fromReader(reader: Reader): ReportResultChooseOption; + } export class ReportResultAddComment extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; optional?: true; option: bytes; }> { - // flags: undefined; + // flags: Api.Type; optional?: true; option: bytes; - }; - export class ReportResultReported extends VirtualClass {}; + static fromReader(reader: Reader): ReportResultAddComment; + } + export class ReportResultReported extends VirtualClass { + static fromReader(reader: Reader): ReportResultReported; + } export class BotAppSettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; placeholderPath?: bytes; backgroundColor?: int; backgroundDarkColor?: int; headerColor?: int; headerDarkColor?: int; } | void> { - // flags: undefined; + // flags: Api.Type; placeholderPath?: bytes; backgroundColor?: int; backgroundDarkColor?: int; headerColor?: int; headerDarkColor?: int; - }; + static fromReader(reader: Reader): BotAppSettings; + } export class StarRefProgram extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; botId: long; commissionPermille: int; durationMonths?: int; endDate?: int; dailyRevenuePerUser?: Api.TypeStarsAmount; }> { - // flags: undefined; + // flags: Api.Type; botId: long; commissionPermille: int; durationMonths?: int; endDate?: int; dailyRevenuePerUser?: Api.TypeStarsAmount; - }; + static fromReader(reader: Reader): StarRefProgram; + } export class ConnectedBotStarRef extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; revoked?: true; url: string; date: int; @@ -10799,7 +12120,7 @@ namespace Api { participants: long; revenue: long; }> { - // flags: undefined; + // flags: Api.Type; revoked?: true; url: string; date: int; @@ -10808,27 +12129,30 @@ namespace Api { durationMonths?: int; participants: long; revenue: long; - }; + static fromReader(reader: Reader): ConnectedBotStarRef; + } export class StarsAmount extends VirtualClass<{ amount: long; nanos: int; }> { amount: long; nanos: int; - }; + static fromReader(reader: Reader): StarsAmount; + } export class BotVerifierSettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; canModifyCustomDescription?: true; icon: long; company: string; customDescription?: string; }> { - // flags: undefined; + // flags: Api.Type; canModifyCustomDescription?: true; icon: long; company: string; customDescription?: string; - }; + static fromReader(reader: Reader): BotVerifierSettings; + } export class BotVerification extends VirtualClass<{ botId: long; icon: long; @@ -10837,7 +12161,8 @@ namespace Api { botId: long; icon: long; description: string; - }; + static fromReader(reader: Reader): BotVerification; + } export class StarGiftAttributeModel extends VirtualClass<{ name: string; document: Api.TypeDocument; @@ -10846,7 +12171,8 @@ namespace Api { name: string; document: Api.TypeDocument; rarityPermille: int; - }; + static fromReader(reader: Reader): StarGiftAttributeModel; + } export class StarGiftAttributePattern extends VirtualClass<{ name: string; document: Api.TypeDocument; @@ -10855,7 +12181,8 @@ namespace Api { name: string; document: Api.TypeDocument; rarityPermille: int; - }; + static fromReader(reader: Reader): StarGiftAttributePattern; + } export class StarGiftAttributeBackdrop extends VirtualClass<{ name: string; centerColor: int; @@ -10870,20 +12197,22 @@ namespace Api { patternColor: int; textColor: int; rarityPermille: int; - }; + static fromReader(reader: Reader): StarGiftAttributeBackdrop; + } export class StarGiftAttributeOriginalDetails extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; senderId?: long; recipientId: long; date: int; message?: Api.TypeTextWithEntities; }> { - // flags: undefined; + // flags: Api.Type; senderId?: long; recipientId: long; date: int; message?: Api.TypeTextWithEntities; - }; + static fromReader(reader: Reader): StarGiftAttributeOriginalDetails; + } export class ResPQ extends VirtualClass<{ nonce: int128; serverNonce: int128; @@ -10894,7 +12223,8 @@ namespace Api { serverNonce: int128; pq: bytes; serverPublicKeyFingerprints: long[]; - }; + static fromReader(reader: Reader): ResPQ; + } export class PQInnerData extends VirtualClass<{ pq: bytes; p: bytes; @@ -10909,7 +12239,8 @@ namespace Api { nonce: int128; serverNonce: int128; newNonce: int256; - }; + static fromReader(reader: Reader): PQInnerData; + } export class PQInnerDataDc extends VirtualClass<{ pq: bytes; p: bytes; @@ -10926,7 +12257,8 @@ namespace Api { serverNonce: int128; newNonce: int256; dc: int; - }; + static fromReader(reader: Reader): PQInnerDataDc; + } export class PQInnerDataTemp extends VirtualClass<{ pq: bytes; p: bytes; @@ -10943,7 +12275,8 @@ namespace Api { serverNonce: int128; newNonce: int256; expiresIn: int; - }; + static fromReader(reader: Reader): PQInnerDataTemp; + } export class PQInnerDataTempDc extends VirtualClass<{ pq: bytes; p: bytes; @@ -10962,7 +12295,8 @@ namespace Api { newNonce: int256; dc: int; expiresIn: int; - }; + static fromReader(reader: Reader): PQInnerDataTempDc; + } export class ServerDHParamsFail extends VirtualClass<{ nonce: int128; serverNonce: int128; @@ -10971,7 +12305,8 @@ namespace Api { nonce: int128; serverNonce: int128; newNonceHash: int128; - }; + static fromReader(reader: Reader): ServerDHParamsFail; + } export class ServerDHParamsOk extends VirtualClass<{ nonce: int128; serverNonce: int128; @@ -10980,7 +12315,8 @@ namespace Api { nonce: int128; serverNonce: int128; encryptedAnswer: bytes; - }; + static fromReader(reader: Reader): ServerDHParamsOk; + } export class ServerDHInnerData extends VirtualClass<{ nonce: int128; serverNonce: int128; @@ -10995,7 +12331,8 @@ namespace Api { dhPrime: bytes; gA: bytes; serverTime: int; - }; + static fromReader(reader: Reader): ServerDHInnerData; + } export class ClientDHInnerData extends VirtualClass<{ nonce: int128; serverNonce: int128; @@ -11006,7 +12343,8 @@ namespace Api { serverNonce: int128; retryId: long; gB: bytes; - }; + static fromReader(reader: Reader): ClientDHInnerData; + } export class DhGenOk extends VirtualClass<{ nonce: int128; serverNonce: int128; @@ -11015,7 +12353,8 @@ namespace Api { nonce: int128; serverNonce: int128; newNonceHash1: int128; - }; + static fromReader(reader: Reader): DhGenOk; + } export class DhGenRetry extends VirtualClass<{ nonce: int128; serverNonce: int128; @@ -11024,7 +12363,8 @@ namespace Api { nonce: int128; serverNonce: int128; newNonceHash2: int128; - }; + static fromReader(reader: Reader): DhGenRetry; + } export class DhGenFail extends VirtualClass<{ nonce: int128; serverNonce: int128; @@ -11033,15 +12373,23 @@ namespace Api { nonce: int128; serverNonce: int128; newNonceHash3: int128; - }; - export class DestroyAuthKeyOk extends VirtualClass {}; - export class DestroyAuthKeyNone extends VirtualClass {}; - export class DestroyAuthKeyFail extends VirtualClass {}; + static fromReader(reader: Reader): DhGenFail; + } + export class DestroyAuthKeyOk extends VirtualClass { + static fromReader(reader: Reader): DestroyAuthKeyOk; + } + export class DestroyAuthKeyNone extends VirtualClass { + static fromReader(reader: Reader): DestroyAuthKeyNone; + } + export class DestroyAuthKeyFail extends VirtualClass { + static fromReader(reader: Reader): DestroyAuthKeyFail; + } export class MsgsAck extends VirtualClass<{ msgIds: long[]; }> { msgIds: long[]; - }; + static fromReader(reader: Reader): MsgsAck; + } export class BadMsgNotification extends VirtualClass<{ badMsgId: long; badMsgSeqno: int; @@ -11050,7 +12398,8 @@ namespace Api { badMsgId: long; badMsgSeqno: int; errorCode: int; - }; + static fromReader(reader: Reader): BadMsgNotification; + } export class BadServerSalt extends VirtualClass<{ badMsgId: long; badMsgSeqno: int; @@ -11061,26 +12410,30 @@ namespace Api { badMsgSeqno: int; errorCode: int; newServerSalt: long; - }; + static fromReader(reader: Reader): BadServerSalt; + } export class MsgsStateReq extends VirtualClass<{ msgIds: long[]; }> { msgIds: long[]; - }; + static fromReader(reader: Reader): MsgsStateReq; + } export class MsgsStateInfo extends VirtualClass<{ reqMsgId: long; info: string; }> { reqMsgId: long; info: string; - }; + static fromReader(reader: Reader): MsgsStateInfo; + } export class MsgsAllInfo extends VirtualClass<{ msgIds: long[]; info: string; }> { msgIds: long[]; info: string; - }; + static fromReader(reader: Reader): MsgsAllInfo; + } export class MsgDetailedInfo extends VirtualClass<{ msgId: long; answerMsgId: long; @@ -11091,7 +12444,8 @@ namespace Api { answerMsgId: long; bytes: int; status: int; - }; + static fromReader(reader: Reader): MsgDetailedInfo; + } export class MsgNewDetailedInfo extends VirtualClass<{ answerMsgId: long; bytes: int; @@ -11100,21 +12454,28 @@ namespace Api { answerMsgId: long; bytes: int; status: int; - }; + static fromReader(reader: Reader): MsgNewDetailedInfo; + } export class MsgResendReq extends VirtualClass<{ msgIds: long[]; }> { msgIds: long[]; - }; + static fromReader(reader: Reader): MsgResendReq; + } export class RpcError extends VirtualClass<{ errorCode: int; errorMessage: string; }> { errorCode: int; errorMessage: string; - }; - export class RpcAnswerUnknown extends VirtualClass {}; - export class RpcAnswerDroppedRunning extends VirtualClass {}; + static fromReader(reader: Reader): RpcError; + } + export class RpcAnswerUnknown extends VirtualClass { + static fromReader(reader: Reader): RpcAnswerUnknown; + } + export class RpcAnswerDroppedRunning extends VirtualClass { + static fromReader(reader: Reader): RpcAnswerDroppedRunning; + } export class RpcAnswerDropped extends VirtualClass<{ msgId: long; seqNo: int; @@ -11123,7 +12484,8 @@ namespace Api { msgId: long; seqNo: int; bytes: int; - }; + static fromReader(reader: Reader): RpcAnswerDropped; + } export class FutureSalt extends VirtualClass<{ validSince: int; validUntil: int; @@ -11132,33 +12494,38 @@ namespace Api { validSince: int; validUntil: int; salt: long; - }; + static fromReader(reader: Reader): FutureSalt; + } export class FutureSalts extends VirtualClass<{ reqMsgId: long; now: int; - salts: future_salt[]; + salts: Api.TypeFutureSalt[]; }> { reqMsgId: long; now: int; - salts: future_salt[]; - }; + salts: Api.TypeFutureSalt[]; + static fromReader(reader: Reader): FutureSalts; + } export class Pong extends VirtualClass<{ msgId: long; pingId: long; }> { msgId: long; pingId: long; - }; + static fromReader(reader: Reader): Pong; + } export class DestroySessionOk extends VirtualClass<{ sessionId: long; }> { sessionId: long; - }; + static fromReader(reader: Reader): DestroySessionOk; + } export class DestroySessionNone extends VirtualClass<{ sessionId: long; }> { sessionId: long; - }; + static fromReader(reader: Reader): DestroySessionNone; + } export class NewSessionCreated extends VirtualClass<{ firstMsgId: long; uniqueId: long; @@ -11167,7 +12534,8 @@ namespace Api { firstMsgId: long; uniqueId: long; serverSalt: long; - }; + static fromReader(reader: Reader): NewSessionCreated; + } export class HttpWait extends VirtualClass<{ maxDelay: int; waitAfter: int; @@ -11176,14 +12544,16 @@ namespace Api { maxDelay: int; waitAfter: int; maxWait: int; - }; + static fromReader(reader: Reader): HttpWait; + } export class IpPort extends VirtualClass<{ ipv4: int; port: int; }> { ipv4: int; port: int; - }; + static fromReader(reader: Reader): IpPort; + } export class IpPortSecret extends VirtualClass<{ ipv4: int; port: int; @@ -11192,7 +12562,8 @@ namespace Api { ipv4: int; port: int; secret: bytes; - }; + static fromReader(reader: Reader): IpPortSecret; + } export class AccessPointRule extends VirtualClass<{ phonePrefixRules: string; dcId: int; @@ -11201,140 +12572,190 @@ namespace Api { phonePrefixRules: string; dcId: int; ips: Api.TypeIpPort[]; - }; + static fromReader(reader: Reader): AccessPointRule; + } export class TlsClientHello extends VirtualClass<{ blocks: Api.TypeTlsBlock[]; }> { blocks: Api.TypeTlsBlock[]; - }; + static fromReader(reader: Reader): TlsClientHello; + } export class TlsBlockString extends VirtualClass<{ data: string; }> { data: string; - }; + static fromReader(reader: Reader): TlsBlockString; + } export class TlsBlockRandom extends VirtualClass<{ length: int; }> { length: int; - }; + static fromReader(reader: Reader): TlsBlockRandom; + } export class TlsBlockZero extends VirtualClass<{ length: int; }> { length: int; - }; - export class TlsBlockDomain extends VirtualClass {}; + static fromReader(reader: Reader): TlsBlockZero; + } + export class TlsBlockDomain extends VirtualClass { + static fromReader(reader: Reader): TlsBlockDomain; + } export class TlsBlockGrease extends VirtualClass<{ seed: int; }> { seed: int; - }; + static fromReader(reader: Reader): TlsBlockGrease; + } export class TlsBlockScope extends VirtualClass<{ entries: Api.TypeTlsBlock[]; }> { entries: Api.TypeTlsBlock[]; - }; + static fromReader(reader: Reader): TlsBlockScope; + } export namespace storage { - export class FileUnknown extends VirtualClass {}; - export class FilePartial extends VirtualClass {}; - export class FileJpeg extends VirtualClass {}; - export class FileGif extends VirtualClass {}; - export class FilePng extends VirtualClass {}; - export class FilePdf extends VirtualClass {}; - export class FileMp3 extends VirtualClass {}; - export class FileMov extends VirtualClass {}; - export class FileMp4 extends VirtualClass {}; - export class FileWebp extends VirtualClass {}; + export class FileUnknown extends VirtualClass { + static fromReader(reader: Reader): FileUnknown; + } + export class FilePartial extends VirtualClass { + static fromReader(reader: Reader): FilePartial; + } + export class FileJpeg extends VirtualClass { + static fromReader(reader: Reader): FileJpeg; + } + export class FileGif extends VirtualClass { + static fromReader(reader: Reader): FileGif; + } + export class FilePng extends VirtualClass { + static fromReader(reader: Reader): FilePng; + } + export class FilePdf extends VirtualClass { + static fromReader(reader: Reader): FilePdf; + } + export class FileMp3 extends VirtualClass { + static fromReader(reader: Reader): FileMp3; + } + export class FileMov extends VirtualClass { + static fromReader(reader: Reader): FileMov; + } + export class FileMp4 extends VirtualClass { + static fromReader(reader: Reader): FileMp4; + } + export class FileWebp extends VirtualClass { + static fromReader(reader: Reader): FileWebp; + } } export namespace auth { export class SentCode extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; type: auth.TypeSentCodeType; phoneCodeHash: string; nextType?: auth.TypeCodeType; timeout?: int; }> { - // flags: undefined; + // flags: Api.Type; type: auth.TypeSentCodeType; phoneCodeHash: string; nextType?: auth.TypeCodeType; timeout?: int; - }; + static fromReader(reader: Reader): SentCode; + } export class SentCodeSuccess extends VirtualClass<{ authorization: auth.TypeAuthorization; }> { authorization: auth.TypeAuthorization; - }; + static fromReader(reader: Reader): SentCodeSuccess; + } export class Authorization extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; setupPasswordRequired?: true; otherwiseReloginDays?: int; tmpSessions?: int; futureAuthToken?: bytes; user: Api.TypeUser; }> { - // flags: undefined; + // flags: Api.Type; setupPasswordRequired?: true; otherwiseReloginDays?: int; tmpSessions?: int; futureAuthToken?: bytes; user: Api.TypeUser; - }; + static fromReader(reader: Reader): Authorization; + } export class AuthorizationSignUpRequired extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; termsOfService?: help.TypeTermsOfService; } | void> { - // flags: undefined; + // flags: Api.Type; termsOfService?: help.TypeTermsOfService; - }; + static fromReader(reader: Reader): AuthorizationSignUpRequired; + } export class ExportedAuthorization extends VirtualClass<{ id: long; bytes: bytes; }> { id: long; bytes: bytes; - }; + static fromReader(reader: Reader): ExportedAuthorization; + } export class PasswordRecovery extends VirtualClass<{ emailPattern: string; }> { emailPattern: string; - }; - export class CodeTypeSms extends VirtualClass {}; - export class CodeTypeCall extends VirtualClass {}; - export class CodeTypeFlashCall extends VirtualClass {}; - export class CodeTypeMissedCall extends VirtualClass {}; - export class CodeTypeFragmentSms extends VirtualClass {}; + static fromReader(reader: Reader): PasswordRecovery; + } + export class CodeTypeSms extends VirtualClass { + static fromReader(reader: Reader): CodeTypeSms; + } + export class CodeTypeCall extends VirtualClass { + static fromReader(reader: Reader): CodeTypeCall; + } + export class CodeTypeFlashCall extends VirtualClass { + static fromReader(reader: Reader): CodeTypeFlashCall; + } + export class CodeTypeMissedCall extends VirtualClass { + static fromReader(reader: Reader): CodeTypeMissedCall; + } + export class CodeTypeFragmentSms extends VirtualClass { + static fromReader(reader: Reader): CodeTypeFragmentSms; + } export class SentCodeTypeApp extends VirtualClass<{ length: int; }> { length: int; - }; + static fromReader(reader: Reader): SentCodeTypeApp; + } export class SentCodeTypeSms extends VirtualClass<{ length: int; }> { length: int; - }; + static fromReader(reader: Reader): SentCodeTypeSms; + } export class SentCodeTypeCall extends VirtualClass<{ length: int; }> { length: int; - }; + static fromReader(reader: Reader): SentCodeTypeCall; + } export class SentCodeTypeFlashCall extends VirtualClass<{ pattern: string; }> { pattern: string; - }; + static fromReader(reader: Reader): SentCodeTypeFlashCall; + } export class SentCodeTypeMissedCall extends VirtualClass<{ prefix: string; length: int; }> { prefix: string; length: int; - }; + static fromReader(reader: Reader): SentCodeTypeMissedCall; + } export class SentCodeTypeEmailCode extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; appleSigninAllowed?: true; googleSigninAllowed?: true; emailPattern: string; @@ -11342,32 +12763,35 @@ namespace Api { resetAvailablePeriod?: int; resetPendingDate?: int; }> { - // flags: undefined; + // flags: Api.Type; appleSigninAllowed?: true; googleSigninAllowed?: true; emailPattern: string; length: int; resetAvailablePeriod?: int; resetPendingDate?: int; - }; + static fromReader(reader: Reader): SentCodeTypeEmailCode; + } export class SentCodeTypeSetUpEmailRequired extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; appleSigninAllowed?: true; googleSigninAllowed?: true; } | void> { - // flags: undefined; + // flags: Api.Type; appleSigninAllowed?: true; googleSigninAllowed?: true; - }; + static fromReader(reader: Reader): SentCodeTypeSetUpEmailRequired; + } export class SentCodeTypeFragmentSms extends VirtualClass<{ url: string; length: int; }> { url: string; length: int; - }; + static fromReader(reader: Reader): SentCodeTypeFragmentSms; + } export class SentCodeTypeFirebaseSms extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; nonce?: bytes; playIntegrityProjectId?: long; playIntegrityNonce?: bytes; @@ -11375,58 +12799,67 @@ namespace Api { pushTimeout?: int; length: int; }> { - // flags: undefined; + // flags: Api.Type; nonce?: bytes; playIntegrityProjectId?: long; playIntegrityNonce?: bytes; receipt?: string; pushTimeout?: int; length: int; - }; + static fromReader(reader: Reader): SentCodeTypeFirebaseSms; + } export class SentCodeTypeSmsWord extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; beginning?: string; } | void> { - // flags: undefined; + // flags: Api.Type; beginning?: string; - }; + static fromReader(reader: Reader): SentCodeTypeSmsWord; + } export class SentCodeTypeSmsPhrase extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; beginning?: string; } | void> { - // flags: undefined; + // flags: Api.Type; beginning?: string; - }; + static fromReader(reader: Reader): SentCodeTypeSmsPhrase; + } export class LoginToken extends VirtualClass<{ expires: int; token: bytes; }> { expires: int; token: bytes; - }; + static fromReader(reader: Reader): LoginToken; + } export class LoginTokenMigrateTo extends VirtualClass<{ dcId: int; token: bytes; }> { dcId: int; token: bytes; - }; + static fromReader(reader: Reader): LoginTokenMigrateTo; + } export class LoginTokenSuccess extends VirtualClass<{ authorization: auth.TypeAuthorization; }> { authorization: auth.TypeAuthorization; - }; + static fromReader(reader: Reader): LoginTokenSuccess; + } export class LoggedOut extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; futureAuthToken?: bytes; } | void> { - // flags: undefined; + // flags: Api.Type; futureAuthToken?: bytes; - }; + static fromReader(reader: Reader): LoggedOut; + } } export namespace contacts { - export class ContactsNotModified extends VirtualClass {}; + export class ContactsNotModified extends VirtualClass { + static fromReader(reader: Reader): ContactsNotModified; + } export class Contacts extends VirtualClass<{ contacts: Api.TypeContact[]; savedCount: int; @@ -11435,7 +12868,8 @@ namespace Api { contacts: Api.TypeContact[]; savedCount: int; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): Contacts; + } export class ImportedContacts extends VirtualClass<{ imported: Api.TypeImportedContact[]; popularInvites: Api.TypePopularContact[]; @@ -11446,7 +12880,8 @@ namespace Api { popularInvites: Api.TypePopularContact[]; retryContacts: long[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ImportedContacts; + } export class Blocked extends VirtualClass<{ blocked: Api.TypePeerBlocked[]; chats: Api.TypeChat[]; @@ -11455,7 +12890,8 @@ namespace Api { blocked: Api.TypePeerBlocked[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): Blocked; + } export class BlockedSlice extends VirtualClass<{ count: int; blocked: Api.TypePeerBlocked[]; @@ -11466,7 +12902,8 @@ namespace Api { blocked: Api.TypePeerBlocked[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): BlockedSlice; + } export class Found extends VirtualClass<{ myResults: Api.TypePeer[]; results: Api.TypePeer[]; @@ -11477,7 +12914,8 @@ namespace Api { results: Api.TypePeer[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): Found; + } export class ResolvedPeer extends VirtualClass<{ peer: Api.TypePeer; chats: Api.TypeChat[]; @@ -11486,8 +12924,11 @@ namespace Api { peer: Api.TypePeer; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; - export class TopPeersNotModified extends VirtualClass {}; + static fromReader(reader: Reader): ResolvedPeer; + } + export class TopPeersNotModified extends VirtualClass { + static fromReader(reader: Reader): TopPeersNotModified; + } export class TopPeers extends VirtualClass<{ categories: Api.TypeTopPeerCategoryPeers[]; chats: Api.TypeChat[]; @@ -11496,15 +12937,19 @@ namespace Api { categories: Api.TypeTopPeerCategoryPeers[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; - export class TopPeersDisabled extends VirtualClass {}; + static fromReader(reader: Reader): TopPeers; + } + export class TopPeersDisabled extends VirtualClass { + static fromReader(reader: Reader): TopPeersDisabled; + } export class ContactBirthdays extends VirtualClass<{ contacts: Api.TypeContactBirthday[]; users: Api.TypeUser[]; }> { contacts: Api.TypeContactBirthday[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ContactBirthdays; + } } export namespace messages { @@ -11518,7 +12963,8 @@ namespace Api { messages: Api.TypeMessage[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): Dialogs; + } export class DialogsSlice extends VirtualClass<{ count: int; dialogs: Api.TypeDialog[]; @@ -11531,12 +12977,14 @@ namespace Api { messages: Api.TypeMessage[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): DialogsSlice; + } export class DialogsNotModified extends VirtualClass<{ count: int; }> { count: int; - }; + static fromReader(reader: Reader): DialogsNotModified; + } export class Messages extends VirtualClass<{ messages: Api.TypeMessage[]; chats: Api.TypeChat[]; @@ -11545,9 +12993,10 @@ namespace Api { messages: Api.TypeMessage[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): Messages; + } export class MessagesSlice extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; inexact?: true; count: int; nextRate?: int; @@ -11556,7 +13005,7 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; inexact?: true; count: int; nextRate?: int; @@ -11564,9 +13013,10 @@ namespace Api { messages: Api.TypeMessage[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): MessagesSlice; + } export class ChannelMessages extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; inexact?: true; pts: int; count: int; @@ -11576,7 +13026,7 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; inexact?: true; pts: int; count: int; @@ -11585,24 +13035,28 @@ namespace Api { topics: Api.TypeForumTopic[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ChannelMessages; + } export class MessagesNotModified extends VirtualClass<{ count: int; }> { count: int; - }; + static fromReader(reader: Reader): MessagesNotModified; + } export class Chats extends VirtualClass<{ chats: Api.TypeChat[]; }> { chats: Api.TypeChat[]; - }; + static fromReader(reader: Reader): Chats; + } export class ChatsSlice extends VirtualClass<{ count: int; chats: Api.TypeChat[]; }> { count: int; chats: Api.TypeChat[]; - }; + static fromReader(reader: Reader): ChatsSlice; + } export class ChatFull extends VirtualClass<{ fullChat: Api.TypeChatFull; chats: Api.TypeChat[]; @@ -11611,7 +13065,8 @@ namespace Api { fullChat: Api.TypeChatFull; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ChatFull; + } export class AffectedHistory extends VirtualClass<{ pts: int; ptsCount: int; @@ -11620,12 +13075,14 @@ namespace Api { pts: int; ptsCount: int; offset: int; - }; + static fromReader(reader: Reader): AffectedHistory; + } export class DhConfigNotModified extends VirtualClass<{ random: bytes; }> { random: bytes; - }; + static fromReader(reader: Reader): DhConfigNotModified; + } export class DhConfig extends VirtualClass<{ g: int; p: bytes; @@ -11636,42 +13093,52 @@ namespace Api { p: bytes; version: int; random: bytes; - }; + static fromReader(reader: Reader): DhConfig; + } export class SentEncryptedMessage extends VirtualClass<{ date: int; }> { date: int; - }; + static fromReader(reader: Reader): SentEncryptedMessage; + } export class SentEncryptedFile extends VirtualClass<{ date: int; file: Api.TypeEncryptedFile; }> { date: int; file: Api.TypeEncryptedFile; - }; - export class StickersNotModified extends VirtualClass {}; + static fromReader(reader: Reader): SentEncryptedFile; + } + export class StickersNotModified extends VirtualClass { + static fromReader(reader: Reader): StickersNotModified; + } export class Stickers extends VirtualClass<{ hash: long; stickers: Api.TypeDocument[]; }> { hash: long; stickers: Api.TypeDocument[]; - }; - export class AllStickersNotModified extends VirtualClass {}; + static fromReader(reader: Reader): Stickers; + } + export class AllStickersNotModified extends VirtualClass { + static fromReader(reader: Reader): AllStickersNotModified; + } export class AllStickers extends VirtualClass<{ hash: long; sets: Api.TypeStickerSet[]; }> { hash: long; sets: Api.TypeStickerSet[]; - }; + static fromReader(reader: Reader): AllStickers; + } export class AffectedMessages extends VirtualClass<{ pts: int; ptsCount: int; }> { pts: int; ptsCount: int; - }; + static fromReader(reader: Reader): AffectedMessages; + } export class StickerSet extends VirtualClass<{ set: Api.TypeStickerSet; packs: Api.TypeStickerPack[]; @@ -11682,18 +13149,24 @@ namespace Api { packs: Api.TypeStickerPack[]; keywords: Api.TypeStickerKeyword[]; documents: Api.TypeDocument[]; - }; - export class StickerSetNotModified extends VirtualClass {}; - export class SavedGifsNotModified extends VirtualClass {}; + static fromReader(reader: Reader): StickerSet; + } + export class StickerSetNotModified extends VirtualClass { + static fromReader(reader: Reader): StickerSetNotModified; + } + export class SavedGifsNotModified extends VirtualClass { + static fromReader(reader: Reader): SavedGifsNotModified; + } export class SavedGifs extends VirtualClass<{ hash: long; gifs: Api.TypeDocument[]; }> { hash: long; gifs: Api.TypeDocument[]; - }; + static fromReader(reader: Reader): SavedGifs; + } export class BotResults extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; gallery?: true; queryId: long; nextOffset?: string; @@ -11703,7 +13176,7 @@ namespace Api { cacheTime: int; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; gallery?: true; queryId: long; nextOffset?: string; @@ -11712,9 +13185,10 @@ namespace Api { results: Api.TypeBotInlineResult[]; cacheTime: int; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): BotResults; + } export class BotCallbackAnswer extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; alert?: true; hasUrl?: true; nativeUi?: true; @@ -11722,21 +13196,23 @@ namespace Api { url?: string; cacheTime: int; }> { - // flags: undefined; + // flags: Api.Type; alert?: true; hasUrl?: true; nativeUi?: true; message?: string; url?: string; cacheTime: int; - }; + static fromReader(reader: Reader): BotCallbackAnswer; + } export class MessageEditData extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; caption?: true; } | void> { - // flags: undefined; + // flags: Api.Type; caption?: true; - }; + static fromReader(reader: Reader): MessageEditData; + } export class PeerDialogs extends VirtualClass<{ dialogs: Api.TypeDialog[]; messages: Api.TypeMessage[]; @@ -11749,28 +13225,33 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; state: updates.TypeState; - }; + static fromReader(reader: Reader): PeerDialogs; + } export class FeaturedStickersNotModified extends VirtualClass<{ count: int; }> { count: int; - }; + static fromReader(reader: Reader): FeaturedStickersNotModified; + } export class FeaturedStickers extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; premium?: true; hash: long; count: int; sets: Api.TypeStickerSetCovered[]; unread: long[]; }> { - // flags: undefined; + // flags: Api.Type; premium?: true; hash: long; count: int; sets: Api.TypeStickerSetCovered[]; unread: long[]; - }; - export class RecentStickersNotModified extends VirtualClass {}; + static fromReader(reader: Reader): FeaturedStickers; + } + export class RecentStickersNotModified extends VirtualClass { + static fromReader(reader: Reader): RecentStickersNotModified; + } export class RecentStickers extends VirtualClass<{ hash: long; packs: Api.TypeStickerPack[]; @@ -11781,28 +13262,36 @@ namespace Api { packs: Api.TypeStickerPack[]; stickers: Api.TypeDocument[]; dates: int[]; - }; + static fromReader(reader: Reader): RecentStickers; + } export class ArchivedStickers extends VirtualClass<{ count: int; sets: Api.TypeStickerSetCovered[]; }> { count: int; sets: Api.TypeStickerSetCovered[]; - }; - export class StickerSetInstallResultSuccess extends VirtualClass {}; + static fromReader(reader: Reader): ArchivedStickers; + } + export class StickerSetInstallResultSuccess extends VirtualClass { + static fromReader(reader: Reader): StickerSetInstallResultSuccess; + } export class StickerSetInstallResultArchive extends VirtualClass<{ sets: Api.TypeStickerSetCovered[]; }> { sets: Api.TypeStickerSetCovered[]; - }; + static fromReader(reader: Reader): StickerSetInstallResultArchive; + } export class HighScores extends VirtualClass<{ scores: Api.TypeHighScore[]; users: Api.TypeUser[]; }> { scores: Api.TypeHighScore[]; users: Api.TypeUser[]; - }; - export class FavedStickersNotModified extends VirtualClass {}; + static fromReader(reader: Reader): HighScores; + } + export class FavedStickersNotModified extends VirtualClass { + static fromReader(reader: Reader): FavedStickersNotModified; + } export class FavedStickers extends VirtualClass<{ hash: long; packs: Api.TypeStickerPack[]; @@ -11811,26 +13300,31 @@ namespace Api { hash: long; packs: Api.TypeStickerPack[]; stickers: Api.TypeDocument[]; - }; - export class FoundStickerSetsNotModified extends VirtualClass {}; + static fromReader(reader: Reader): FavedStickers; + } + export class FoundStickerSetsNotModified extends VirtualClass { + static fromReader(reader: Reader): FoundStickerSetsNotModified; + } export class FoundStickerSets extends VirtualClass<{ hash: long; sets: Api.TypeStickerSetCovered[]; }> { hash: long; sets: Api.TypeStickerSetCovered[]; - }; + static fromReader(reader: Reader): FoundStickerSets; + } export class SearchCounter extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; inexact?: true; filter: Api.TypeMessagesFilter; count: int; }> { - // flags: undefined; + // flags: Api.Type; inexact?: true; filter: Api.TypeMessagesFilter; count: int; - }; + static fromReader(reader: Reader): SearchCounter; + } export class InactiveChats extends VirtualClass<{ dates: int[]; chats: Api.TypeChat[]; @@ -11839,22 +13333,24 @@ namespace Api { dates: int[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): InactiveChats; + } export class VotesList extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; count: int; votes: Api.TypeMessagePeerVote[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; nextOffset?: string; }> { - // flags: undefined; + // flags: Api.Type; count: int; votes: Api.TypeMessagePeerVote[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; nextOffset?: string; - }; + static fromReader(reader: Reader): VotesList; + } export class MessageViews extends VirtualClass<{ views: Api.TypeMessageViews[]; chats: Api.TypeChat[]; @@ -11863,9 +13359,10 @@ namespace Api { views: Api.TypeMessageViews[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): MessageViews; + } export class DiscussionMessage extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; messages: Api.TypeMessage[]; maxId?: int; readInboxMaxId?: int; @@ -11874,7 +13371,7 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; messages: Api.TypeMessage[]; maxId?: int; readInboxMaxId?: int; @@ -11882,23 +13379,26 @@ namespace Api { unreadCount: int; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): DiscussionMessage; + } export class HistoryImport extends VirtualClass<{ id: long; }> { id: long; - }; + static fromReader(reader: Reader): HistoryImport; + } export class HistoryImportParsed extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; pm?: true; group?: true; title?: string; } | void> { - // flags: undefined; + // flags: Api.Type; pm?: true; group?: true; title?: string; - }; + static fromReader(reader: Reader): HistoryImportParsed; + } export class AffectedFoundMessages extends VirtualClass<{ pts: int; ptsCount: int; @@ -11909,7 +13409,8 @@ namespace Api { ptsCount: int; offset: int; messages: int[]; - }; + static fromReader(reader: Reader): AffectedFoundMessages; + } export class ExportedChatInvites extends VirtualClass<{ count: int; invites: Api.TypeExportedChatInvite[]; @@ -11918,14 +13419,16 @@ namespace Api { count: int; invites: Api.TypeExportedChatInvite[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ExportedChatInvites; + } export class ExportedChatInvite extends VirtualClass<{ invite: Api.TypeExportedChatInvite; users: Api.TypeUser[]; }> { invite: Api.TypeExportedChatInvite; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ExportedChatInvite; + } export class ExportedChatInviteReplaced extends VirtualClass<{ invite: Api.TypeExportedChatInvite; newInvite: Api.TypeExportedChatInvite; @@ -11934,7 +13437,8 @@ namespace Api { invite: Api.TypeExportedChatInvite; newInvite: Api.TypeExportedChatInvite; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ExportedChatInviteReplaced; + } export class ChatInviteImporters extends VirtualClass<{ count: int; importers: Api.TypeChatInviteImporter[]; @@ -11943,35 +13447,41 @@ namespace Api { count: int; importers: Api.TypeChatInviteImporter[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ChatInviteImporters; + } export class ChatAdminsWithInvites extends VirtualClass<{ admins: Api.TypeChatAdminWithInvites[]; users: Api.TypeUser[]; }> { admins: Api.TypeChatAdminWithInvites[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ChatAdminsWithInvites; + } export class CheckedHistoryImportPeer extends VirtualClass<{ confirmText: string; }> { confirmText: string; - }; + static fromReader(reader: Reader): CheckedHistoryImportPeer; + } export class SponsoredMessages extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; postsBetween?: int; messages: Api.TypeSponsoredMessage[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; postsBetween?: int; messages: Api.TypeSponsoredMessage[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; - export class SponsoredMessagesEmpty extends VirtualClass {}; + static fromReader(reader: Reader): SponsoredMessages; + } + export class SponsoredMessagesEmpty extends VirtualClass { + static fromReader(reader: Reader): SponsoredMessagesEmpty; + } export class SearchResultsCalendar extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; inexact?: true; count: int; minDate: int; @@ -11982,7 +13492,7 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; inexact?: true; count: int; minDate: int; @@ -11992,14 +13502,16 @@ namespace Api { messages: Api.TypeMessage[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): SearchResultsCalendar; + } export class SearchResultsPositions extends VirtualClass<{ count: int; positions: Api.TypeSearchResultsPosition[]; }> { count: int; positions: Api.TypeSearchResultsPosition[]; - }; + static fromReader(reader: Reader): SearchResultsPositions; + } export class PeerSettings extends VirtualClass<{ settings: Api.TypePeerSettings; chats: Api.TypeChat[]; @@ -12008,55 +13520,64 @@ namespace Api { settings: Api.TypePeerSettings; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): PeerSettings; + } export class MessageReactionsList extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; count: int; reactions: Api.TypeMessagePeerReaction[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; nextOffset?: string; }> { - // flags: undefined; + // flags: Api.Type; count: int; reactions: Api.TypeMessagePeerReaction[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; nextOffset?: string; - }; - export class AvailableReactionsNotModified extends VirtualClass {}; + static fromReader(reader: Reader): MessageReactionsList; + } + export class AvailableReactionsNotModified extends VirtualClass { + static fromReader(reader: Reader): AvailableReactionsNotModified; + } export class AvailableReactions extends VirtualClass<{ hash: int; reactions: Api.TypeAvailableReaction[]; }> { hash: int; reactions: Api.TypeAvailableReaction[]; - }; + static fromReader(reader: Reader): AvailableReactions; + } export class TranscribedAudio extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; pending?: true; transcriptionId: long; text: string; trialRemainsNum?: int; trialRemainsUntilDate?: int; }> { - // flags: undefined; + // flags: Api.Type; pending?: true; transcriptionId: long; text: string; trialRemainsNum?: int; trialRemainsUntilDate?: int; - }; - export class ReactionsNotModified extends VirtualClass {}; + static fromReader(reader: Reader): TranscribedAudio; + } + export class ReactionsNotModified extends VirtualClass { + static fromReader(reader: Reader): ReactionsNotModified; + } export class Reactions extends VirtualClass<{ hash: long; reactions: Api.TypeReaction[]; }> { hash: long; reactions: Api.TypeReaction[]; - }; + static fromReader(reader: Reader): Reactions; + } export class ForumTopics extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; orderByCreateDate?: true; count: int; topics: Api.TypeForumTopic[]; @@ -12065,7 +13586,7 @@ namespace Api { users: Api.TypeUser[]; pts: int; }> { - // flags: undefined; + // flags: Api.Type; orderByCreateDate?: true; count: int; topics: Api.TypeForumTopic[]; @@ -12073,33 +13594,39 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; pts: int; - }; - export class EmojiGroupsNotModified extends VirtualClass {}; + static fromReader(reader: Reader): ForumTopics; + } + export class EmojiGroupsNotModified extends VirtualClass { + static fromReader(reader: Reader): EmojiGroupsNotModified; + } export class EmojiGroups extends VirtualClass<{ hash: int; groups: Api.TypeEmojiGroup[]; }> { hash: int; groups: Api.TypeEmojiGroup[]; - }; + static fromReader(reader: Reader): EmojiGroups; + } export class TranslateResult extends VirtualClass<{ result: Api.TypeTextWithEntities[]; }> { result: Api.TypeTextWithEntities[]; - }; + static fromReader(reader: Reader): TranslateResult; + } export class BotApp extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; inactive?: true; requestWriteAccess?: true; hasSettings?: true; app: Api.TypeBotApp; }> { - // flags: undefined; + // flags: Api.Type; inactive?: true; requestWriteAccess?: true; hasSettings?: true; app: Api.TypeBotApp; - }; + static fromReader(reader: Reader): BotApp; + } export class WebPage extends VirtualClass<{ webpage: Api.TypeWebPage; chats: Api.TypeChat[]; @@ -12108,7 +13635,8 @@ namespace Api { webpage: Api.TypeWebPage; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): WebPage; + } export class SavedDialogs extends VirtualClass<{ dialogs: Api.TypeSavedDialog[]; messages: Api.TypeMessage[]; @@ -12119,7 +13647,8 @@ namespace Api { messages: Api.TypeMessage[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): SavedDialogs; + } export class SavedDialogsSlice extends VirtualClass<{ count: int; dialogs: Api.TypeSavedDialog[]; @@ -12132,20 +13661,25 @@ namespace Api { messages: Api.TypeMessage[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): SavedDialogsSlice; + } export class SavedDialogsNotModified extends VirtualClass<{ count: int; }> { count: int; - }; - export class SavedReactionTagsNotModified extends VirtualClass {}; + static fromReader(reader: Reader): SavedDialogsNotModified; + } + export class SavedReactionTagsNotModified extends VirtualClass { + static fromReader(reader: Reader): SavedReactionTagsNotModified; + } export class SavedReactionTags extends VirtualClass<{ tags: Api.TypeSavedReactionTag[]; hash: long; }> { tags: Api.TypeSavedReactionTag[]; hash: long; - }; + static fromReader(reader: Reader): SavedReactionTags; + } export class QuickReplies extends VirtualClass<{ quickReplies: Api.TypeQuickReply[]; messages: Api.TypeMessage[]; @@ -12156,32 +13690,40 @@ namespace Api { messages: Api.TypeMessage[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; - export class QuickRepliesNotModified extends VirtualClass {}; + static fromReader(reader: Reader): QuickReplies; + } + export class QuickRepliesNotModified extends VirtualClass { + static fromReader(reader: Reader): QuickRepliesNotModified; + } export class DialogFilters extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; tagsEnabled?: true; filters: Api.TypeDialogFilter[]; }> { - // flags: undefined; + // flags: Api.Type; tagsEnabled?: true; filters: Api.TypeDialogFilter[]; - }; + static fromReader(reader: Reader): DialogFilters; + } export class MyStickers extends VirtualClass<{ count: int; sets: Api.TypeStickerSetCovered[]; }> { count: int; sets: Api.TypeStickerSetCovered[]; - }; + static fromReader(reader: Reader): MyStickers; + } export class InvitedUsers extends VirtualClass<{ updates: Api.TypeUpdates; missingInvitees: Api.TypeMissingInvitee[]; }> { updates: Api.TypeUpdates; missingInvitees: Api.TypeMissingInvitee[]; - }; - export class AvailableEffectsNotModified extends VirtualClass {}; + static fromReader(reader: Reader): InvitedUsers; + } + export class AvailableEffectsNotModified extends VirtualClass { + static fromReader(reader: Reader): AvailableEffectsNotModified; + } export class AvailableEffects extends VirtualClass<{ hash: int; effects: Api.TypeAvailableEffect[]; @@ -12190,14 +13732,16 @@ namespace Api { hash: int; effects: Api.TypeAvailableEffect[]; documents: Api.TypeDocument[]; - }; + static fromReader(reader: Reader): AvailableEffects; + } export class BotPreparedInlineMessage extends VirtualClass<{ id: string; expireDate: int; }> { id: string; expireDate: int; - }; + static fromReader(reader: Reader): BotPreparedInlineMessage; + } export class PreparedInlineMessage extends VirtualClass<{ queryId: long; result: Api.TypeBotInlineResult; @@ -12210,32 +13754,36 @@ namespace Api { peerTypes: Api.TypeInlineQueryPeerType[]; cacheTime: int; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): PreparedInlineMessage; + } export class FoundStickersNotModified extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; nextOffset?: int; } | void> { - // flags: undefined; + // flags: Api.Type; nextOffset?: int; - }; + static fromReader(reader: Reader): FoundStickersNotModified; + } export class FoundStickers extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; nextOffset?: int; hash: long; stickers: Api.TypeDocument[]; }> { - // flags: undefined; + // flags: Api.Type; nextOffset?: int; hash: long; stickers: Api.TypeDocument[]; - }; + static fromReader(reader: Reader): FoundStickers; + } export class WebPagePreview extends VirtualClass<{ media: Api.TypeMessageMedia; users: Api.TypeUser[]; }> { media: Api.TypeMessageMedia; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): WebPagePreview; + } } export namespace updates { @@ -12251,14 +13799,16 @@ namespace Api { date: int; seq: int; unreadCount: int; - }; + static fromReader(reader: Reader): State; + } export class DifferenceEmpty extends VirtualClass<{ date: int; seq: int; }> { date: int; seq: int; - }; + static fromReader(reader: Reader): DifferenceEmpty; + } export class Difference extends VirtualClass<{ newMessages: Api.TypeMessage[]; newEncryptedMessages: Api.TypeEncryptedMessage[]; @@ -12273,7 +13823,8 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; state: updates.TypeState; - }; + static fromReader(reader: Reader): Difference; + } export class DifferenceSlice extends VirtualClass<{ newMessages: Api.TypeMessage[]; newEncryptedMessages: Api.TypeEncryptedMessage[]; @@ -12288,25 +13839,28 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; intermediateState: updates.TypeState; - }; + static fromReader(reader: Reader): DifferenceSlice; + } export class DifferenceTooLong extends VirtualClass<{ pts: int; }> { pts: int; - }; + static fromReader(reader: Reader): DifferenceTooLong; + } export class ChannelDifferenceEmpty extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; final?: true; pts: int; timeout?: int; }> { - // flags: undefined; + // flags: Api.Type; final?: true; pts: int; timeout?: int; - }; + static fromReader(reader: Reader): ChannelDifferenceEmpty; + } export class ChannelDifferenceTooLong extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; final?: true; timeout?: int; dialog: Api.TypeDialog; @@ -12314,16 +13868,17 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; final?: true; timeout?: int; dialog: Api.TypeDialog; messages: Api.TypeMessage[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ChannelDifferenceTooLong; + } export class ChannelDifference extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; final?: true; pts: int; timeout?: int; @@ -12332,7 +13887,7 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; final?: true; pts: int; timeout?: int; @@ -12340,7 +13895,8 @@ namespace Api { otherUpdates: Api.TypeUpdate[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ChannelDifference; + } } export namespace photos { @@ -12350,7 +13906,8 @@ namespace Api { }> { photos: Api.TypePhoto[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): Photos; + } export class PhotosSlice extends VirtualClass<{ count: int; photos: Api.TypePhoto[]; @@ -12359,14 +13916,16 @@ namespace Api { count: int; photos: Api.TypePhoto[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): PhotosSlice; + } export class Photo extends VirtualClass<{ photo: Api.TypePhoto; users: Api.TypeUser[]; }> { photo: Api.TypePhoto; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): Photo; + } } export namespace upload { @@ -12378,7 +13937,8 @@ namespace Api { type: storage.TypeFileType; mtime: int; bytes: bytes; - }; + static fromReader(reader: Reader): File; + } export class FileCdnRedirect extends VirtualClass<{ dcId: int; fileToken: bytes; @@ -12391,7 +13951,8 @@ namespace Api { encryptionKey: bytes; encryptionIv: bytes; fileHashes: Api.TypeFileHash[]; - }; + static fromReader(reader: Reader): FileCdnRedirect; + } export class WebFile extends VirtualClass<{ size: int; mimeType: string; @@ -12404,22 +13965,25 @@ namespace Api { fileType: storage.TypeFileType; mtime: int; bytes: bytes; - }; + static fromReader(reader: Reader): WebFile; + } export class CdnFileReuploadNeeded extends VirtualClass<{ requestToken: bytes; }> { requestToken: bytes; - }; + static fromReader(reader: Reader): CdnFileReuploadNeeded; + } export class CdnFile extends VirtualClass<{ bytes: bytes; }> { bytes: bytes; - }; + static fromReader(reader: Reader): CdnFile; + } } export namespace help { export class AppUpdate extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; canNotSkip?: true; id: int; version: string; @@ -12429,7 +13993,7 @@ namespace Api { url?: string; sticker?: Api.TypeDocument; }> { - // flags: undefined; + // flags: Api.Type; canNotSkip?: true; id: int; version: string; @@ -12438,35 +14002,41 @@ namespace Api { document?: Api.TypeDocument; url?: string; sticker?: Api.TypeDocument; - }; - export class NoAppUpdate extends VirtualClass {}; + static fromReader(reader: Reader): AppUpdate; + } + export class NoAppUpdate extends VirtualClass { + static fromReader(reader: Reader): NoAppUpdate; + } export class InviteText extends VirtualClass<{ message: string; }> { message: string; - }; + static fromReader(reader: Reader): InviteText; + } export class Support extends VirtualClass<{ phoneNumber: string; user: Api.TypeUser; }> { phoneNumber: string; user: Api.TypeUser; - }; + static fromReader(reader: Reader): Support; + } export class TermsOfService extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; popup?: true; id: Api.TypeDataJSON; text: string; entities: Api.TypeMessageEntity[]; minAgeConfirm?: int; }> { - // flags: undefined; + // flags: Api.Type; popup?: true; id: Api.TypeDataJSON; text: string; entities: Api.TypeMessageEntity[]; minAgeConfirm?: int; - }; + static fromReader(reader: Reader): TermsOfService; + } export class RecentMeUrls extends VirtualClass<{ urls: Api.TypeRecentMeUrl[]; chats: Api.TypeChat[]; @@ -12475,45 +14045,57 @@ namespace Api { urls: Api.TypeRecentMeUrl[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): RecentMeUrls; + } export class TermsOfServiceUpdateEmpty extends VirtualClass<{ expires: int; }> { expires: int; - }; + static fromReader(reader: Reader): TermsOfServiceUpdateEmpty; + } export class TermsOfServiceUpdate extends VirtualClass<{ expires: int; termsOfService: help.TypeTermsOfService; }> { expires: int; termsOfService: help.TypeTermsOfService; - }; - export class DeepLinkInfoEmpty extends VirtualClass {}; + static fromReader(reader: Reader): TermsOfServiceUpdate; + } + export class DeepLinkInfoEmpty extends VirtualClass { + static fromReader(reader: Reader): DeepLinkInfoEmpty; + } export class DeepLinkInfo extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; updateApp?: true; message: string; entities?: Api.TypeMessageEntity[]; }> { - // flags: undefined; + // flags: Api.Type; updateApp?: true; message: string; entities?: Api.TypeMessageEntity[]; - }; - export class PassportConfigNotModified extends VirtualClass {}; + static fromReader(reader: Reader): DeepLinkInfo; + } + export class PassportConfigNotModified extends VirtualClass { + static fromReader(reader: Reader): PassportConfigNotModified; + } export class PassportConfig extends VirtualClass<{ hash: int; countriesLangs: Api.TypeDataJSON; }> { hash: int; countriesLangs: Api.TypeDataJSON; - }; + static fromReader(reader: Reader): PassportConfig; + } export class SupportName extends VirtualClass<{ name: string; }> { name: string; - }; - export class UserInfoEmpty extends VirtualClass {}; + static fromReader(reader: Reader): SupportName; + } + export class UserInfoEmpty extends VirtualClass { + static fromReader(reader: Reader): UserInfoEmpty; + } export class UserInfo extends VirtualClass<{ message: string; entities: Api.TypeMessageEntity[]; @@ -12524,14 +14106,16 @@ namespace Api { entities: Api.TypeMessageEntity[]; author: string; date: int; - }; + static fromReader(reader: Reader): UserInfo; + } export class PromoDataEmpty extends VirtualClass<{ expires: int; }> { expires: int; - }; + static fromReader(reader: Reader): PromoDataEmpty; + } export class PromoData extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; proxy?: true; expires: int; peer: Api.TypePeer; @@ -12540,7 +14124,7 @@ namespace Api { psaType?: string; psaMessage?: string; }> { - // flags: undefined; + // flags: Api.Type; proxy?: true; expires: int; peer: Api.TypePeer; @@ -12548,41 +14132,47 @@ namespace Api { users: Api.TypeUser[]; psaType?: string; psaMessage?: string; - }; + static fromReader(reader: Reader): PromoData; + } export class CountryCode extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; countryCode: string; prefixes?: string[]; patterns?: string[]; }> { - // flags: undefined; + // flags: Api.Type; countryCode: string; prefixes?: string[]; patterns?: string[]; - }; + static fromReader(reader: Reader): CountryCode; + } export class Country extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; hidden?: true; iso2: string; defaultName: string; name?: string; countryCodes: help.TypeCountryCode[]; }> { - // flags: undefined; + // flags: Api.Type; hidden?: true; iso2: string; defaultName: string; name?: string; countryCodes: help.TypeCountryCode[]; - }; - export class CountriesListNotModified extends VirtualClass {}; + static fromReader(reader: Reader): Country; + } + export class CountriesListNotModified extends VirtualClass { + static fromReader(reader: Reader): CountriesListNotModified; + } export class CountriesList extends VirtualClass<{ countries: help.TypeCountry[]; hash: int; }> { countries: help.TypeCountry[]; hash: int; - }; + static fromReader(reader: Reader): CountriesList; + } export class PremiumPromo extends VirtualClass<{ statusText: string; statusEntities: Api.TypeMessageEntity[]; @@ -12597,20 +14187,25 @@ namespace Api { videos: Api.TypeDocument[]; periodOptions: Api.TypePremiumSubscriptionOption[]; users: Api.TypeUser[]; - }; - export class AppConfigNotModified extends VirtualClass {}; + static fromReader(reader: Reader): PremiumPromo; + } + export class AppConfigNotModified extends VirtualClass { + static fromReader(reader: Reader): AppConfigNotModified; + } export class AppConfig extends VirtualClass<{ hash: int; config: Api.TypeJSONValue; }> { hash: int; config: Api.TypeJSONValue; - }; + static fromReader(reader: Reader): AppConfig; + } export class PeerColorSet extends VirtualClass<{ colors: int[]; }> { colors: int[]; - }; + static fromReader(reader: Reader): PeerColorSet; + } export class PeerColorProfileSet extends VirtualClass<{ paletteColors: int[]; bgColors: int[]; @@ -12619,9 +14214,10 @@ namespace Api { paletteColors: int[]; bgColors: int[]; storyColors: int[]; - }; + static fromReader(reader: Reader): PeerColorProfileSet; + } export class PeerColorOption extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; hidden?: true; colorId: int; colors?: help.TypePeerColorSet; @@ -12629,30 +14225,37 @@ namespace Api { channelMinLevel?: int; groupMinLevel?: int; }> { - // flags: undefined; + // flags: Api.Type; hidden?: true; colorId: int; colors?: help.TypePeerColorSet; darkColors?: help.TypePeerColorSet; channelMinLevel?: int; groupMinLevel?: int; - }; - export class PeerColorsNotModified extends VirtualClass {}; + static fromReader(reader: Reader): PeerColorOption; + } + export class PeerColorsNotModified extends VirtualClass { + static fromReader(reader: Reader): PeerColorsNotModified; + } export class PeerColors extends VirtualClass<{ hash: int; colors: help.TypePeerColorOption[]; }> { hash: int; colors: help.TypePeerColorOption[]; - }; - export class TimezonesListNotModified extends VirtualClass {}; + static fromReader(reader: Reader): PeerColors; + } + export class TimezonesListNotModified extends VirtualClass { + static fromReader(reader: Reader): TimezonesListNotModified; + } export class TimezonesList extends VirtualClass<{ timezones: Api.TypeTimezone[]; hash: int; }> { timezones: Api.TypeTimezone[]; hash: int; - }; + static fromReader(reader: Reader): TimezonesList; + } export class ConfigSimple extends VirtualClass<{ date: int; expires: int; @@ -12661,7 +14264,8 @@ namespace Api { date: int; expires: int; rules: Api.TypeAccessPointRule[]; - }; + static fromReader(reader: Reader): ConfigSimple; + } } export namespace account { @@ -12673,16 +14277,18 @@ namespace Api { rules: Api.TypePrivacyRule[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): PrivacyRules; + } export class Authorizations extends VirtualClass<{ authorizationTtlDays: int; authorizations: Api.TypeAuthorization[]; }> { authorizationTtlDays: int; authorizations: Api.TypeAuthorization[]; - }; + static fromReader(reader: Reader): Authorizations; + } export class Password extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; hasRecovery?: true; hasSecureValues?: true; hasPassword?: true; @@ -12697,7 +14303,7 @@ namespace Api { pendingResetDate?: int; loginEmailPattern?: string; }> { - // flags: undefined; + // flags: Api.Type; hasRecovery?: true; hasSecureValues?: true; hasPassword?: true; @@ -12711,80 +14317,91 @@ namespace Api { secureRandom: bytes; pendingResetDate?: int; loginEmailPattern?: string; - }; + static fromReader(reader: Reader): Password; + } export class PasswordSettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; email?: string; secureSettings?: Api.TypeSecureSecretSettings; } | void> { - // flags: undefined; + // flags: Api.Type; email?: string; secureSettings?: Api.TypeSecureSecretSettings; - }; + static fromReader(reader: Reader): PasswordSettings; + } export class PasswordInputSettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; newAlgo?: Api.TypePasswordKdfAlgo; newPasswordHash?: bytes; hint?: string; email?: string; newSecureSettings?: Api.TypeSecureSecretSettings; } | void> { - // flags: undefined; + // flags: Api.Type; newAlgo?: Api.TypePasswordKdfAlgo; newPasswordHash?: bytes; hint?: string; email?: string; newSecureSettings?: Api.TypeSecureSecretSettings; - }; + static fromReader(reader: Reader): PasswordInputSettings; + } export class TmpPassword extends VirtualClass<{ tmpPassword: bytes; validUntil: int; }> { tmpPassword: bytes; validUntil: int; - }; + static fromReader(reader: Reader): TmpPassword; + } export class WebAuthorizations extends VirtualClass<{ authorizations: Api.TypeWebAuthorization[]; users: Api.TypeUser[]; }> { authorizations: Api.TypeWebAuthorization[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): WebAuthorizations; + } export class AuthorizationForm extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; requiredTypes: Api.TypeSecureRequiredType[]; values: Api.TypeSecureValue[]; errors: Api.TypeSecureValueError[]; users: Api.TypeUser[]; privacyPolicyUrl?: string; }> { - // flags: undefined; + // flags: Api.Type; requiredTypes: Api.TypeSecureRequiredType[]; values: Api.TypeSecureValue[]; errors: Api.TypeSecureValueError[]; users: Api.TypeUser[]; privacyPolicyUrl?: string; - }; + static fromReader(reader: Reader): AuthorizationForm; + } export class SentEmailCode extends VirtualClass<{ emailPattern: string; length: int; }> { emailPattern: string; length: int; - }; + static fromReader(reader: Reader): SentEmailCode; + } export class Takeout extends VirtualClass<{ id: long; }> { id: long; - }; - export class WallPapersNotModified extends VirtualClass {}; + static fromReader(reader: Reader): Takeout; + } + export class WallPapersNotModified extends VirtualClass { + static fromReader(reader: Reader): WallPapersNotModified; + } export class WallPapers extends VirtualClass<{ hash: long; wallpapers: Api.TypeWallPaper[]; }> { hash: long; wallpapers: Api.TypeWallPaper[]; - }; + static fromReader(reader: Reader): WallPapers; + } export class AutoDownloadSettings extends VirtualClass<{ low: Api.TypeAutoDownloadSettings; medium: Api.TypeAutoDownloadSettings; @@ -12793,69 +14410,89 @@ namespace Api { low: Api.TypeAutoDownloadSettings; medium: Api.TypeAutoDownloadSettings; high: Api.TypeAutoDownloadSettings; - }; - export class ThemesNotModified extends VirtualClass {}; + static fromReader(reader: Reader): AutoDownloadSettings; + } + export class ThemesNotModified extends VirtualClass { + static fromReader(reader: Reader): ThemesNotModified; + } export class Themes extends VirtualClass<{ hash: long; themes: Api.TypeTheme[]; }> { hash: long; themes: Api.TypeTheme[]; - }; + static fromReader(reader: Reader): Themes; + } export class ContentSettings extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; sensitiveEnabled?: true; sensitiveCanChange?: true; } | void> { - // flags: undefined; + // flags: Api.Type; sensitiveEnabled?: true; sensitiveCanChange?: true; - }; + static fromReader(reader: Reader): ContentSettings; + } export class ResetPasswordFailedWait extends VirtualClass<{ retryDate: int; }> { retryDate: int; - }; + static fromReader(reader: Reader): ResetPasswordFailedWait; + } export class ResetPasswordRequestedWait extends VirtualClass<{ untilDate: int; }> { untilDate: int; - }; - export class ResetPasswordOk extends VirtualClass {}; - export class SavedRingtonesNotModified extends VirtualClass {}; + static fromReader(reader: Reader): ResetPasswordRequestedWait; + } + export class ResetPasswordOk extends VirtualClass { + static fromReader(reader: Reader): ResetPasswordOk; + } + export class SavedRingtonesNotModified extends VirtualClass { + static fromReader(reader: Reader): SavedRingtonesNotModified; + } export class SavedRingtones extends VirtualClass<{ hash: long; ringtones: Api.TypeDocument[]; }> { hash: long; ringtones: Api.TypeDocument[]; - }; - export class SavedRingtone extends VirtualClass {}; + static fromReader(reader: Reader): SavedRingtones; + } + export class SavedRingtone extends VirtualClass { + static fromReader(reader: Reader): SavedRingtone; + } export class SavedRingtoneConverted extends VirtualClass<{ document: Api.TypeDocument; }> { document: Api.TypeDocument; - }; - export class EmojiStatusesNotModified extends VirtualClass {}; + static fromReader(reader: Reader): SavedRingtoneConverted; + } + export class EmojiStatusesNotModified extends VirtualClass { + static fromReader(reader: Reader): EmojiStatusesNotModified; + } export class EmojiStatuses extends VirtualClass<{ hash: long; statuses: Api.TypeEmojiStatus[]; }> { hash: long; statuses: Api.TypeEmojiStatus[]; - }; + static fromReader(reader: Reader): EmojiStatuses; + } export class EmailVerified extends VirtualClass<{ email: string; }> { email: string; - }; + static fromReader(reader: Reader): EmailVerified; + } export class EmailVerifiedLogin extends VirtualClass<{ email: string; sentCode: auth.TypeSentCode; }> { email: string; sentCode: auth.TypeSentCode; - }; + static fromReader(reader: Reader): EmailVerifiedLogin; + } export class AutoSaveSettings extends VirtualClass<{ usersSettings: Api.TypeAutoSaveSettings; chatsSettings: Api.TypeAutoSaveSettings; @@ -12870,14 +14507,16 @@ namespace Api { exceptions: Api.TypeAutoSaveException[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): AutoSaveSettings; + } export class ConnectedBots extends VirtualClass<{ connectedBots: Api.TypeConnectedBot[]; users: Api.TypeUser[]; }> { connectedBots: Api.TypeConnectedBot[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ConnectedBots; + } export class BusinessChatLinks extends VirtualClass<{ links: Api.TypeBusinessChatLink[]; chats: Api.TypeChat[]; @@ -12886,22 +14525,24 @@ namespace Api { links: Api.TypeBusinessChatLink[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): BusinessChatLinks; + } export class ResolvedBusinessChatLinks extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; message: string; entities?: Api.TypeMessageEntity[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypePeer; message: string; entities?: Api.TypeMessageEntity[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ResolvedBusinessChatLinks; + } } export namespace channels { @@ -12915,8 +14556,11 @@ namespace Api { participants: Api.TypeChannelParticipant[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; - export class ChannelParticipantsNotModified extends VirtualClass {}; + static fromReader(reader: Reader): ChannelParticipants; + } + export class ChannelParticipantsNotModified extends VirtualClass { + static fromReader(reader: Reader): ChannelParticipantsNotModified; + } export class ChannelParticipant extends VirtualClass<{ participant: Api.TypeChannelParticipant; chats: Api.TypeChat[]; @@ -12925,7 +14569,8 @@ namespace Api { participant: Api.TypeChannelParticipant; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ChannelParticipant; + } export class AdminLogResults extends VirtualClass<{ events: Api.TypeChannelAdminLogEvent[]; chats: Api.TypeChat[]; @@ -12934,7 +14579,8 @@ namespace Api { events: Api.TypeChannelAdminLogEvent[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): AdminLogResults; + } export class SendAsPeers extends VirtualClass<{ peers: Api.TypeSendAsPeer[]; chats: Api.TypeChat[]; @@ -12943,21 +14589,27 @@ namespace Api { peers: Api.TypeSendAsPeer[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): SendAsPeers; + } export class SponsoredMessageReportResultChooseOption extends VirtualClass<{ title: string; options: Api.TypeSponsoredMessageReportOption[]; }> { title: string; options: Api.TypeSponsoredMessageReportOption[]; - }; - export class SponsoredMessageReportResultAdsHidden extends VirtualClass {}; - export class SponsoredMessageReportResultReported extends VirtualClass {}; + static fromReader(reader: Reader): SponsoredMessageReportResultChooseOption; + } + export class SponsoredMessageReportResultAdsHidden extends VirtualClass { + static fromReader(reader: Reader): SponsoredMessageReportResultAdsHidden; + } + export class SponsoredMessageReportResultReported extends VirtualClass { + static fromReader(reader: Reader): SponsoredMessageReportResultReported; + } } export namespace payments { export class PaymentForm extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; canSaveCredentials?: true; passwordMissing?: true; formId: long; @@ -12975,7 +14627,7 @@ namespace Api { savedCredentials?: Api.TypePaymentSavedCredentials[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; canSaveCredentials?: true; passwordMissing?: true; formId: long; @@ -12992,9 +14644,10 @@ namespace Api { savedInfo?: Api.TypePaymentRequestedInfo; savedCredentials?: Api.TypePaymentSavedCredentials[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): PaymentForm; + } export class PaymentFormStars extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; formId: long; botId: long; title: string; @@ -13003,7 +14656,7 @@ namespace Api { invoice: Api.TypeInvoice; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; formId: long; botId: long; title: string; @@ -13011,35 +14664,40 @@ namespace Api { photo?: Api.TypeWebDocument; invoice: Api.TypeInvoice; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): PaymentFormStars; + } export class PaymentFormStarGift extends VirtualClass<{ formId: long; invoice: Api.TypeInvoice; }> { formId: long; invoice: Api.TypeInvoice; - }; + static fromReader(reader: Reader): PaymentFormStarGift; + } export class ValidatedRequestedInfo extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; id?: string; shippingOptions?: Api.TypeShippingOption[]; } | void> { - // flags: undefined; + // flags: Api.Type; id?: string; shippingOptions?: Api.TypeShippingOption[]; - }; + static fromReader(reader: Reader): ValidatedRequestedInfo; + } export class PaymentResult extends VirtualClass<{ updates: Api.TypeUpdates; }> { updates: Api.TypeUpdates; - }; + static fromReader(reader: Reader): PaymentResult; + } export class PaymentVerificationNeeded extends VirtualClass<{ url: string; }> { url: string; - }; + static fromReader(reader: Reader): PaymentVerificationNeeded; + } export class PaymentReceipt extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; date: int; botId: long; providerId: long; @@ -13055,7 +14713,7 @@ namespace Api { credentialsTitle: string; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; date: int; botId: long; providerId: long; @@ -13070,9 +14728,10 @@ namespace Api { totalAmount: long; credentialsTitle: string; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): PaymentReceipt; + } export class PaymentReceiptStars extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; date: int; botId: long; title: string; @@ -13084,7 +14743,7 @@ namespace Api { transactionId: string; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; date: int; botId: long; title: string; @@ -13095,30 +14754,34 @@ namespace Api { totalAmount: long; transactionId: string; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): PaymentReceiptStars; + } export class SavedInfo extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; hasSavedCredentials?: true; savedInfo?: Api.TypePaymentRequestedInfo; } | void> { - // flags: undefined; + // flags: Api.Type; hasSavedCredentials?: true; savedInfo?: Api.TypePaymentRequestedInfo; - }; + static fromReader(reader: Reader): SavedInfo; + } export class BankCardData extends VirtualClass<{ title: string; openUrls: Api.TypeBankCardOpenUrl[]; }> { title: string; openUrls: Api.TypeBankCardOpenUrl[]; - }; + static fromReader(reader: Reader): BankCardData; + } export class ExportedInvoice extends VirtualClass<{ url: string; }> { url: string; - }; + static fromReader(reader: Reader): ExportedInvoice; + } export class CheckedGiftCode extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; viaGiveaway?: true; fromId?: Api.TypePeer; giveawayMsgId?: int; @@ -13129,7 +14792,7 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; viaGiveaway?: true; fromId?: Api.TypePeer; giveawayMsgId?: int; @@ -13139,9 +14802,10 @@ namespace Api { usedDate?: int; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): CheckedGiftCode; + } export class GiveawayInfo extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; participating?: true; preparingResults?: true; startDate: int; @@ -13149,16 +14813,17 @@ namespace Api { adminDisallowedChatId?: long; disallowedCountry?: string; }> { - // flags: undefined; + // flags: Api.Type; participating?: true; preparingResults?: true; startDate: int; joinedTooEarlyDate?: int; adminDisallowedChatId?: long; disallowedCountry?: string; - }; + static fromReader(reader: Reader): GiveawayInfo; + } export class GiveawayInfoResults extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; winner?: true; refunded?: true; startDate: int; @@ -13168,7 +14833,7 @@ namespace Api { winnersCount: int; activatedCount?: int; }> { - // flags: undefined; + // flags: Api.Type; winner?: true; refunded?: true; startDate: int; @@ -13177,9 +14842,10 @@ namespace Api { finishDate: int; winnersCount: int; activatedCount?: int; - }; + static fromReader(reader: Reader): GiveawayInfoResults; + } export class StarsStatus extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; balance: Api.TypeStarsAmount; subscriptions?: Api.TypeStarsSubscription[]; subscriptionsNextOffset?: string; @@ -13189,7 +14855,7 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; balance: Api.TypeStarsAmount; subscriptions?: Api.TypeStarsSubscription[]; subscriptionsNextOffset?: string; @@ -13198,7 +14864,8 @@ namespace Api { nextOffset?: string; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): StarsStatus; + } export class StarsRevenueStats extends VirtualClass<{ revenueGraph: Api.TypeStatsGraph; status: Api.TypeStarsRevenueStatus; @@ -13207,38 +14874,45 @@ namespace Api { revenueGraph: Api.TypeStatsGraph; status: Api.TypeStarsRevenueStatus; usdRate: double; - }; + static fromReader(reader: Reader): StarsRevenueStats; + } export class StarsRevenueWithdrawalUrl extends VirtualClass<{ url: string; }> { url: string; - }; + static fromReader(reader: Reader): StarsRevenueWithdrawalUrl; + } export class StarsRevenueAdsAccountUrl extends VirtualClass<{ url: string; }> { url: string; - }; - export class StarGiftsNotModified extends VirtualClass {}; + static fromReader(reader: Reader): StarsRevenueAdsAccountUrl; + } + export class StarGiftsNotModified extends VirtualClass { + static fromReader(reader: Reader): StarGiftsNotModified; + } export class StarGifts extends VirtualClass<{ hash: int; gifts: Api.TypeStarGift[]; }> { hash: int; gifts: Api.TypeStarGift[]; - }; + static fromReader(reader: Reader): StarGifts; + } export class UserStarGifts extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; count: int; gifts: Api.TypeUserStarGift[]; nextOffset?: string; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; count: int; gifts: Api.TypeUserStarGift[]; nextOffset?: string; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): UserStarGifts; + } export class ConnectedStarRefBots extends VirtualClass<{ count: int; connectedBots: Api.TypeConnectedBotStarRef[]; @@ -13247,32 +14921,36 @@ namespace Api { count: int; connectedBots: Api.TypeConnectedBotStarRef[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ConnectedStarRefBots; + } export class SuggestedStarRefBots extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; count: int; suggestedBots: Api.TypeStarRefProgram[]; users: Api.TypeUser[]; nextOffset?: string; }> { - // flags: undefined; + // flags: Api.Type; count: int; suggestedBots: Api.TypeStarRefProgram[]; users: Api.TypeUser[]; nextOffset?: string; - }; + static fromReader(reader: Reader): SuggestedStarRefBots; + } export class StarGiftUpgradePreview extends VirtualClass<{ sampleAttributes: Api.TypeStarGiftAttribute[]; }> { sampleAttributes: Api.TypeStarGiftAttribute[]; - }; + static fromReader(reader: Reader): StarGiftUpgradePreview; + } export class UniqueStarGift extends VirtualClass<{ gift: Api.TypeStarGift; users: Api.TypeUser[]; }> { gift: Api.TypeStarGift; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): UniqueStarGift; + } } export namespace phone { @@ -13282,7 +14960,8 @@ namespace Api { }> { phoneCall: Api.TypePhoneCall; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): PhoneCall; + } export class GroupCall extends VirtualClass<{ call: Api.TypeGroupCall; participants: Api.TypeGroupCallParticipant[]; @@ -13295,7 +14974,8 @@ namespace Api { participantsNextOffset: string; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): GroupCall; + } export class GroupParticipants extends VirtualClass<{ count: int; participants: Api.TypeGroupCallParticipant[]; @@ -13310,7 +14990,8 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; version: int; - }; + static fromReader(reader: Reader): GroupParticipants; + } export class JoinAsPeers extends VirtualClass<{ peers: Api.TypePeer[]; chats: Api.TypeChat[]; @@ -13319,24 +15000,28 @@ namespace Api { peers: Api.TypePeer[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): JoinAsPeers; + } export class ExportedGroupCallInvite extends VirtualClass<{ link: string; }> { link: string; - }; + static fromReader(reader: Reader): ExportedGroupCallInvite; + } export class GroupCallStreamChannels extends VirtualClass<{ channels: Api.TypeGroupCallStreamChannel[]; }> { channels: Api.TypeGroupCallStreamChannel[]; - }; + static fromReader(reader: Reader): GroupCallStreamChannels; + } export class GroupCallStreamRtmpUrl extends VirtualClass<{ url: string; key: string; }> { url: string; key: string; - }; + static fromReader(reader: Reader): GroupCallStreamRtmpUrl; + } } export namespace stats { @@ -13386,7 +15071,8 @@ namespace Api { storyInteractionsGraph: Api.TypeStatsGraph; storyReactionsByEmotionGraph: Api.TypeStatsGraph; recentPostsInteractions: Api.TypePostInteractionCounters[]; - }; + static fromReader(reader: Reader): BroadcastStats; + } export class MegagroupStats extends VirtualClass<{ period: Api.TypeStatsDateRangeDays; members: Api.TypeStatsAbsValueAndPrev; @@ -13423,36 +15109,40 @@ namespace Api { topAdmins: Api.TypeStatsGroupTopAdmin[]; topInviters: Api.TypeStatsGroupTopInviter[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): MegagroupStats; + } export class MessageStats extends VirtualClass<{ viewsGraph: Api.TypeStatsGraph; reactionsByEmotionGraph: Api.TypeStatsGraph; }> { viewsGraph: Api.TypeStatsGraph; reactionsByEmotionGraph: Api.TypeStatsGraph; - }; + static fromReader(reader: Reader): MessageStats; + } export class StoryStats extends VirtualClass<{ viewsGraph: Api.TypeStatsGraph; reactionsByEmotionGraph: Api.TypeStatsGraph; }> { viewsGraph: Api.TypeStatsGraph; reactionsByEmotionGraph: Api.TypeStatsGraph; - }; + static fromReader(reader: Reader): StoryStats; + } export class PublicForwards extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; count: int; forwards: Api.TypePublicForward[]; nextOffset?: string; chats: Api.TypeChat[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; count: int; forwards: Api.TypePublicForward[]; nextOffset?: string; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): PublicForwards; + } export class BroadcastRevenueStats extends VirtualClass<{ topHoursGraph: Api.TypeStatsGraph; revenueGraph: Api.TypeStatsGraph; @@ -13463,19 +15153,22 @@ namespace Api { revenueGraph: Api.TypeStatsGraph; balances: Api.TypeBroadcastRevenueBalances; usdRate: double; - }; + static fromReader(reader: Reader): BroadcastRevenueStats; + } export class BroadcastRevenueWithdrawalUrl extends VirtualClass<{ url: string; }> { url: string; - }; + static fromReader(reader: Reader): BroadcastRevenueWithdrawalUrl; + } export class BroadcastRevenueTransactions extends VirtualClass<{ count: int; transactions: Api.TypeBroadcastRevenueTransaction[]; }> { count: int; transactions: Api.TypeBroadcastRevenueTransaction[]; - }; + static fromReader(reader: Reader): BroadcastRevenueTransactions; + } } export namespace stickers { @@ -13483,7 +15176,8 @@ namespace Api { shortName: string; }> { shortName: string; - }; + static fromReader(reader: Reader): SuggestedShortName; + } } export namespace users { @@ -13495,19 +15189,22 @@ namespace Api { fullUser: Api.TypeUserFull; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): UserFull; + } export class Users extends VirtualClass<{ users: Api.TypeUser[]; }> { users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): Users; + } export class UsersSlice extends VirtualClass<{ count: int; users: Api.TypeUser[]; }> { count: int; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): UsersSlice; + } } export namespace chatlists { @@ -13517,7 +15214,8 @@ namespace Api { }> { filter: Api.TypeDialogFilter; invite: Api.TypeExportedChatlistInvite; - }; + static fromReader(reader: Reader): ExportedChatlistInvite; + } export class ExportedInvites extends VirtualClass<{ invites: Api.TypeExportedChatlistInvite[]; chats: Api.TypeChat[]; @@ -13526,7 +15224,8 @@ namespace Api { invites: Api.TypeExportedChatlistInvite[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ExportedInvites; + } export class ChatlistInviteAlready extends VirtualClass<{ filterId: int; missingPeers: Api.TypePeer[]; @@ -13539,9 +15238,10 @@ namespace Api { alreadyPeers: Api.TypePeer[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ChatlistInviteAlready; + } export class ChatlistInvite extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; titleNoanimate?: true; title: Api.TypeTextWithEntities; emoticon?: string; @@ -13549,14 +15249,15 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; titleNoanimate?: true; title: Api.TypeTextWithEntities; emoticon?: string; peers: Api.TypePeer[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ChatlistInvite; + } export class ChatlistUpdates extends VirtualClass<{ missingPeers: Api.TypePeer[]; chats: Api.TypeChat[]; @@ -13565,7 +15266,8 @@ namespace Api { missingPeers: Api.TypePeer[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): ChatlistUpdates; + } } export namespace bots { @@ -13577,37 +15279,41 @@ namespace Api { name: string; about: string; description: string; - }; + static fromReader(reader: Reader): BotInfo; + } export class PopularAppBots extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; nextOffset?: string; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; nextOffset?: string; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): PopularAppBots; + } export class PreviewInfo extends VirtualClass<{ media: Api.TypeBotPreviewMedia[]; langCodes: string[]; }> { media: Api.TypeBotPreviewMedia[]; langCodes: string[]; - }; + static fromReader(reader: Reader): PreviewInfo; + } } export namespace stories { export class AllStoriesNotModified extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; state: string; stealthMode: Api.TypeStoriesStealthMode; }> { - // flags: undefined; + // flags: Api.Type; state: string; stealthMode: Api.TypeStoriesStealthMode; - }; + static fromReader(reader: Reader): AllStoriesNotModified; + } export class AllStories extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; hasMore?: true; count: int; state: string; @@ -13616,7 +15322,7 @@ namespace Api { users: Api.TypeUser[]; stealthMode: Api.TypeStoriesStealthMode; }> { - // flags: undefined; + // flags: Api.Type; hasMore?: true; count: int; state: string; @@ -13624,24 +15330,26 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; stealthMode: Api.TypeStoriesStealthMode; - }; + static fromReader(reader: Reader): AllStories; + } export class Stories extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; count: int; stories: Api.TypeStoryItem[]; pinnedToTop?: int[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; count: int; stories: Api.TypeStoryItem[]; pinnedToTop?: int[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): Stories; + } export class StoryViewsList extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; count: int; viewsCount: int; forwardsCount: int; @@ -13651,7 +15359,7 @@ namespace Api { users: Api.TypeUser[]; nextOffset?: string; }> { - // flags: undefined; + // flags: Api.Type; count: int; viewsCount: int; forwardsCount: int; @@ -13660,14 +15368,16 @@ namespace Api { chats: Api.TypeChat[]; users: Api.TypeUser[]; nextOffset?: string; - }; + static fromReader(reader: Reader): StoryViewsList; + } export class StoryViews extends VirtualClass<{ views: Api.TypeStoryViews[]; users: Api.TypeUser[]; }> { views: Api.TypeStoryViews[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): StoryViews; + } export class PeerStories extends VirtualClass<{ stories: Api.TypePeerStories; chats: Api.TypeChat[]; @@ -13676,53 +15386,57 @@ namespace Api { stories: Api.TypePeerStories; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): PeerStories; + } export class StoryReactionsList extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; count: int; reactions: Api.TypeStoryReaction[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; nextOffset?: string; }> { - // flags: undefined; + // flags: Api.Type; count: int; reactions: Api.TypeStoryReaction[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; nextOffset?: string; - }; + static fromReader(reader: Reader): StoryReactionsList; + } export class FoundStories extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; count: int; stories: Api.TypeFoundStory[]; nextOffset?: string; chats: Api.TypeChat[]; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; count: int; stories: Api.TypeFoundStory[]; nextOffset?: string; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): FoundStories; + } } export namespace premium { export class BoostsList extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; count: int; boosts: Api.TypeBoost[]; nextOffset?: string; users: Api.TypeUser[]; }> { - // flags: undefined; + // flags: Api.Type; count: int; boosts: Api.TypeBoost[]; nextOffset?: string; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): BoostsList; + } export class MyBoosts extends VirtualClass<{ myBoosts: Api.TypeMyBoost[]; chats: Api.TypeChat[]; @@ -13731,9 +15445,10 @@ namespace Api { myBoosts: Api.TypeMyBoost[]; chats: Api.TypeChat[]; users: Api.TypeUser[]; - }; + static fromReader(reader: Reader): MyBoosts; + } export class BoostsStatus extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; myBoost?: true; level: int; currentLevelBoosts: int; @@ -13745,7 +15460,7 @@ namespace Api { prepaidGiveaways?: Api.TypePrepaidGiveaway[]; myBoostSlots?: int[]; }> { - // flags: undefined; + // flags: Api.Type; myBoost?: true; level: int; currentLevelBoosts: int; @@ -13756,7 +15471,8 @@ namespace Api { boostUrl: string; prepaidGiveaways?: Api.TypePrepaidGiveaway[]; myBoostSlots?: int[]; - }; + static fromReader(reader: Reader): BoostsStatus; + } } export namespace smsjobs { @@ -13766,9 +15482,10 @@ namespace Api { }> { termsUrl: string; monthlySentSms: int; - }; + static fromReader(reader: Reader): EligibleToJoin; + } export class Status extends VirtualClass<{ - // flags: undefined; + // flags: Api.Type; allowInternational?: true; recentSent: int; recentSince: int; @@ -13778,7 +15495,7 @@ namespace Api { lastGiftSlug?: string; termsUrl: string; }> { - // flags: undefined; + // flags: Api.Type; allowInternational?: true; recentSent: int; recentSince: int; @@ -13787,7 +15504,8 @@ namespace Api { totalSince: int; lastGiftSlug?: string; termsUrl: string; - }; + static fromReader(reader: Reader): Status; + } } export namespace fragment { @@ -13805,7 +15523,8 @@ namespace Api { cryptoCurrency: string; cryptoAmount: long; url: string; - }; + static fromReader(reader: Reader): CollectibleInfo; + } } export class InvokeAfterMsg extends Request, X> { msgId: long; query: X; - }; + } export class InvokeAfterMsgs extends Request, X> { msgIds: long[]; query: X; - }; + } export class InitConnection extends Request, X> { - // flags: undefined; + // flags: Api.Type; apiId: int; deviceModel: string; systemVersion: string; @@ -13846,40 +15565,40 @@ namespace Api { proxy?: Api.TypeInputClientProxy; params?: Api.TypeJSONValue; query: X; - }; + } export class InvokeWithLayer extends Request, X> { layer: int; query: X; - }; + } export class InvokeWithoutUpdates extends Request, X> { query: X; - }; + } export class InvokeWithMessagesRange extends Request, X> { range: Api.TypeMessageRange; query: X; - }; + } export class InvokeWithTakeout extends Request, X> { takeoutId: long; query: X; - }; + } export class InvokeWithBusinessConnection extends Request, X> { connectionId: string; query: X; - }; + } export class InvokeWithGooglePlayIntegrity extends Request, Api.TypeResPQ> { nonce: int128; - }; + } export class ReqPqMulti extends Request, Api.TypeResPQ> { nonce: int128; - }; + } export class ReqPqMultiNew extends Request, Api.TypeResPQ> { nonce: int128; - }; + } export class ReqDHParams extends Request {}; + } + export class DestroyAuthKey extends Request {} export class RpcDropAnswer extends Request, Api.TypeRpcDropAnswer> { reqMsgId: long; - }; + } export class GetFutureSalts extends Request, Api.TypeFutureSalts> { num: int; - }; + } export class Ping extends Request, Api.TypePong> { pingId: long; - }; + } export class PingDelayDisconnect extends Request, Api.TypePong> { pingId: long; disconnectDelay: int; - }; + } export class DestroySession extends Request, Api.TypeDestroySessionRes> { sessionId: long; - }; + } export namespace auth { @@ -13978,49 +15697,49 @@ namespace Api { apiId: int; apiHash: string; settings: Api.TypeCodeSettings; - }; + } export class SignUp extends Request, auth.TypeAuthorization> { - // flags: undefined; + // flags: Api.Type; noJoinedNotifications?: true; phoneNumber: string; phoneCodeHash: string; firstName: string; lastName: string; - }; + } export class SignIn extends Request, auth.TypeAuthorization> { - // flags: undefined; + // flags: Api.Type; phoneNumber: string; phoneCodeHash: string; phoneCode?: string; emailVerification?: Api.TypeEmailVerification; - }; - export class LogOut extends Request {}; - export class ResetAuthorizations extends Request {}; + } + export class LogOut extends Request {} + export class ResetAuthorizations extends Request {} export class ExportAuthorization extends Request, auth.TypeExportedAuthorization> { dcId: int; - }; + } export class ImportAuthorization extends Request, auth.TypeAuthorization> { id: long; bytes: bytes; - }; + } export class BindTempAuthKey extends Request, auth.TypeAuthorization> { password: Api.TypeInputCheckPasswordSRP; - }; - export class RequestPasswordRecovery extends Request {}; + } + export class RequestPasswordRecovery extends Request {} export class RecoverPassword extends Request, auth.TypeAuthorization> { - // flags: undefined; + // flags: Api.Type; code: string; newSettings?: account.TypePasswordInputSettings; - }; + } export class ResendCode extends Request, auth.TypeSentCode> { - // flags: undefined; + // flags: Api.Type; phoneNumber: string; phoneCodeHash: string; reason?: string; - }; + } export class CancelCode extends Request, Bool> { phoneNumber: string; phoneCodeHash: string; - }; + } export class DropTempAuthKeys extends Request, Bool> { exceptAuthKeys: long[]; - }; + } export class ExportLoginToken extends Request, auth.TypeLoginToken> { token: bytes; - }; + } export class AcceptLoginToken extends Request, Api.TypeAuthorization> { token: bytes; - }; + } export class CheckRecoveryPassword extends Request, Bool> { code: string; - }; + } export class ImportWebTokenAuthorization extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; phoneNumber: string; phoneCodeHash: string; safetyNetToken?: string; playIntegrityToken?: string; iosPushSecret?: string; - }; + } export class ResetLoginEmail extends Request, auth.TypeSentCode> { phoneNumber: string; phoneCodeHash: string; - }; + } export class ReportMissingCode extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; noMuted?: true; tokenType: int; token: string; appSandbox: Bool; secret: bytes; otherUids: long[]; - }; + } export class UnregisterDevice extends Request, Bool> { peer: Api.TypeInputNotifyPeer; settings: Api.TypeInputPeerNotifySettings; - }; + } export class GetNotifySettings extends Request, Api.TypePeerNotifySettings> { peer: Api.TypeInputNotifyPeer; - }; - export class ResetNotifySettings extends Request {}; + } + export class ResetNotifySettings extends Request {} export class UpdateProfile extends Request, Api.TypeUser> { - // flags: undefined; + // flags: Api.Type; firstName?: string; lastName?: string; about?: string; - }; + } export class UpdateStatus extends Request, Bool> { offline: Bool; - }; + } export class GetWallPapers extends Request, account.TypeWallPapers> { hash: long; - }; + } export class ReportPeer extends Request, Bool> { username: string; - }; + } export class UpdateUsername extends Request, Api.TypeUser> { username: string; - }; + } export class GetPrivacy extends Request, account.TypePrivacyRules> { key: Api.TypeInputPrivacyKey; - }; + } export class SetPrivacy extends Request, account.TypePrivacyRules> { key: Api.TypeInputPrivacyKey; rules: Api.TypeInputPrivacyRule[]; - }; + } export class DeleteAccount extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; reason: string; password?: Api.TypeInputCheckPasswordSRP; - }; - export class GetAccountTTL extends Request {}; + } + export class GetAccountTTL extends Request {} export class SetAccountTTL extends Request, Bool> { ttl: Api.TypeAccountDaysTTL; - }; + } export class SendChangePhoneCode extends Request, auth.TypeSentCode> { phoneNumber: string; settings: Api.TypeCodeSettings; - }; + } export class ChangePhone extends Request, Bool> { period: int; - }; - export class GetAuthorizations extends Request {}; + } + export class GetAuthorizations extends Request {} export class ResetAuthorization extends Request, Bool> { hash: long; - }; - export class GetPassword extends Request {}; + } + export class GetPassword extends Request {} export class GetPasswordSettings extends Request, account.TypePasswordSettings> { password: Api.TypeInputCheckPasswordSRP; - }; + } export class UpdatePasswordSettings extends Request, Bool> { password: Api.TypeInputCheckPasswordSRP; newSettings: account.TypePasswordInputSettings; - }; + } export class SendConfirmPhoneCode extends Request, auth.TypeSentCode> { hash: string; settings: Api.TypeCodeSettings; - }; + } export class ConfirmPhone extends Request, Bool> { phoneCodeHash: string; phoneCode: string; - }; + } export class GetTmpPassword extends Request, account.TypeTmpPassword> { password: Api.TypeInputCheckPasswordSRP; period: int; - }; - export class GetWebAuthorizations extends Request {}; + } + export class GetWebAuthorizations extends Request {} export class ResetWebAuthorization extends Request, Bool> { hash: long; - }; - export class ResetWebAuthorizations extends Request {}; - export class GetAllSecureValues extends Request {}; + } + export class ResetWebAuthorizations extends Request {} + export class GetAllSecureValues extends Request {} export class GetSecureValue extends Request, Api.TypeSecureValue[]> { types: Api.TypeSecureValueType[]; - }; + } export class SaveSecureValue extends Request, Api.TypeSecureValue> { value: Api.TypeInputSecureValue; secureSecretId: long; - }; + } export class DeleteSecureValue extends Request, Bool> { types: Api.TypeSecureValueType[]; - }; + } export class GetAuthorizationForm extends Request, auth.TypeSentCode> { phoneNumber: string; settings: Api.TypeCodeSettings; - }; + } export class VerifyPhone extends Request, account.TypeSentEmailCode> { purpose: Api.TypeEmailVerifyPurpose; email: string; - }; + } export class VerifyEmail extends Request, account.TypeEmailVerified> { purpose: Api.TypeEmailVerifyPurpose; verification: Api.TypeEmailVerification; - }; + } export class InitTakeoutSession extends Request, account.TypeTakeout> { - // flags: undefined; + // flags: Api.Type; contacts?: true; messageUsers?: true; messageChats?: true; @@ -14410,56 +16129,56 @@ namespace Api { messageChannels?: true; files?: true; fileMaxSize?: long; - }; + } export class FinishTakeoutSession extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; success?: true; - }; + } export class ConfirmPasswordEmail extends Request, Bool> { code: string; - }; - export class ResendPasswordEmail extends Request {}; - export class CancelPasswordEmail extends Request {}; - export class GetContactSignUpNotification extends Request {}; + } + export class ResendPasswordEmail extends Request {} + export class CancelPasswordEmail extends Request {} + export class GetContactSignUpNotification extends Request {} export class SetContactSignUpNotification extends Request, Bool> { silent: Bool; - }; + } export class GetNotifyExceptions extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; compareSound?: true; compareStories?: true; peer?: Api.TypeInputNotifyPeer; - }; + } export class GetWallPaper extends Request, Api.TypeWallPaper> { wallpaper: Api.TypeInputWallPaper; - }; + } export class UploadWallPaper extends Request, Api.TypeWallPaper> { - // flags: undefined; + // flags: Api.Type; forChat?: true; file: Api.TypeInputFile; mimeType: string; settings: Api.TypeWallPaperSettings; - }; + } export class SaveWallPaper extends Request, Bool> { wallpaper: Api.TypeInputWallPaper; settings: Api.TypeWallPaperSettings; - }; - export class ResetWallPapers extends Request {}; - export class GetAutoDownloadSettings extends Request {}; + } + export class ResetWallPapers extends Request {} + export class GetAutoDownloadSettings extends Request {} export class SaveAutoDownloadSettings extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; low?: true; high?: true; settings: Api.TypeAutoDownloadSettings; - }; + } export class UploadTheme extends Request, Api.TypeDocument> { - // flags: undefined; + // flags: Api.Type; file: Api.TypeInputFile; thumb?: Api.TypeInputFile; fileName: string; mimeType: string; - }; + } export class CreateTheme extends Request, Api.TypeTheme> { - // flags: undefined; + // flags: Api.Type; slug: string; title: string; document?: Api.TypeInputDocument; settings?: Api.TypeInputThemeSettings[]; - }; + } export class UpdateTheme extends Request, Api.TypeTheme> { - // flags: undefined; + // flags: Api.Type; format: string; theme: Api.TypeInputTheme; slug?: string; title?: string; document?: Api.TypeInputDocument; settings?: Api.TypeInputThemeSettings[]; - }; + } export class SaveTheme extends Request, Bool> { theme: Api.TypeInputTheme; unsave: Bool; - }; + } export class InstallTheme extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; dark?: true; theme?: Api.TypeInputTheme; format?: string; baseTheme?: Api.TypeBaseTheme; - }; + } export class GetTheme extends Request, Api.TypeTheme> { format: string; theme: Api.TypeInputTheme; - }; + } export class GetThemes extends Request, account.TypeThemes> { format: string; hash: long; - }; + } export class SetContentSettings extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; sensitiveEnabled?: true; - }; - export class GetContentSettings extends Request {}; + } + export class GetContentSettings extends Request {} export class GetMultiWallPapers extends Request, Api.TypeWallPaper[]> { wallpapers: Api.TypeInputWallPaper[]; - }; - export class GetGlobalPrivacySettings extends Request {}; + } + export class GetGlobalPrivacySettings extends Request {} export class SetGlobalPrivacySettings extends Request, Api.TypeGlobalPrivacySettings> { settings: Api.TypeGlobalPrivacySettings; - }; + } export class ReportProfilePhoto extends Request {}; - export class DeclinePasswordReset extends Request {}; + } + export class ResetPassword extends Request {} + export class DeclinePasswordReset extends Request {} export class GetChatThemes extends Request, account.TypeThemes> { hash: long; - }; + } export class SetAuthorizationTTL extends Request, Bool> { authorizationTtlDays: int; - }; + } export class ChangeAuthorizationSettings extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; confirmed?: true; hash: long; encryptedRequestsDisabled?: Bool; callRequestsDisabled?: Bool; - }; + } export class GetSavedRingtones extends Request, account.TypeSavedRingtones> { hash: long; - }; + } export class SaveRingtone extends Request, account.TypeSavedRingtone> { id: Api.TypeInputDocument; unsave: Bool; - }; + } export class UploadRingtone extends Request, Bool> { emojiStatus: Api.TypeEmojiStatus; - }; + } export class GetDefaultEmojiStatuses extends Request, account.TypeEmojiStatuses> { hash: long; - }; + } export class GetRecentEmojiStatuses extends Request, account.TypeEmojiStatuses> { hash: long; - }; - export class ClearRecentEmojiStatuses extends Request {}; + } + export class ClearRecentEmojiStatuses extends Request {} export class ReorderUsernames extends Request, Bool> { order: string[]; - }; + } export class ToggleUsername extends Request, Bool> { username: string; active: Bool; - }; + } export class GetDefaultProfilePhotoEmojis extends Request, Api.TypeEmojiList> { hash: long; - }; + } export class GetDefaultGroupPhotoEmojis extends Request, Api.TypeEmojiList> { hash: long; - }; - export class GetAutoSaveSettings extends Request {}; + } + export class GetAutoSaveSettings extends Request {} export class SaveAutoSaveSettings extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; users?: true; chats?: true; broadcasts?: true; peer?: Api.TypeInputPeer; settings: Api.TypeAutoSaveSettings; - }; - export class DeleteAutoSaveExceptions extends Request {}; + } + export class DeleteAutoSaveExceptions extends Request {} export class InvalidateSignInCodes extends Request, Bool> { codes: string[]; - }; + } export class UpdateColor extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; forProfile?: true; color?: int; backgroundEmojiId?: long; - }; + } export class GetDefaultBackgroundEmojis extends Request, Api.TypeEmojiList> { hash: long; - }; + } export class GetChannelDefaultEmojiStatuses extends Request, account.TypeEmojiStatuses> { hash: long; - }; + } export class GetChannelRestrictedStatusEmojis extends Request, Api.TypeEmojiList> { hash: long; - }; + } export class UpdateBusinessWorkHours extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; businessWorkHours?: Api.TypeBusinessWorkHours; - }; + } export class UpdateBusinessLocation extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; geoPoint?: Api.TypeInputGeoPoint; address?: string; - }; + } export class UpdateBusinessGreetingMessage extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; message?: Api.TypeInputBusinessGreetingMessage; - }; + } export class UpdateBusinessAwayMessage extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; message?: Api.TypeInputBusinessAwayMessage; - }; + } export class UpdateConnectedBot extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; canReply?: true; deleted?: true; bot: Api.TypeInputUser; recipients: Api.TypeInputBusinessBotRecipients; - }; - export class GetConnectedBots extends Request {}; + } + export class GetConnectedBots extends Request {} export class GetBotBusinessConnection extends Request, Api.TypeUpdates> { connectionId: string; - }; + } export class UpdateBusinessIntro extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; intro?: Api.TypeInputBusinessIntro; - }; + } export class ToggleConnectedBotPaused extends Request, Bool> { peer: Api.TypeInputPeer; paused: Bool; - }; + } export class DisablePeerConnectedBot extends Request, Bool> { peer: Api.TypeInputPeer; - }; + } export class UpdateBirthday extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; birthday?: Api.TypeBirthday; - }; + } export class CreateBusinessChatLink extends Request, Api.TypeBusinessChatLink> { link: Api.TypeInputBusinessChatLink; - }; + } export class EditBusinessChatLink extends Request, Api.TypeBusinessChatLink> { slug: string; link: Api.TypeInputBusinessChatLink; - }; + } export class DeleteBusinessChatLink extends Request, Bool> { slug: string; - }; - export class GetBusinessChatLinks extends Request {}; + } + export class GetBusinessChatLinks extends Request {} export class ResolveBusinessChatLink extends Request, account.TypeResolvedBusinessChatLinks> { slug: string; - }; + } export class UpdatePersonalChannel extends Request, Bool> { channel: Api.TypeInputChannel; - }; + } export class ToggleSponsoredMessages extends Request, Bool> { enabled: Bool; - }; - export class GetReactionsNotifySettings extends Request {}; + } + export class GetReactionsNotifySettings extends Request {} export class SetReactionsNotifySettings extends Request, Api.TypeReactionsNotifySettings> { settings: Api.TypeReactionsNotifySettings; - }; + } } export namespace users { @@ -14849,24 +16568,24 @@ namespace Api { id: Api.TypeInputUser[]; }>, Api.TypeUser[]> { id: Api.TypeInputUser[]; - }; + } export class GetFullUser extends Request, users.TypeUserFull> { id: Api.TypeInputUser; - }; + } export class SetSecureValueErrors extends Request, Bool> { id: Api.TypeInputUser; errors: Api.TypeSecureValueError[]; - }; + } export class GetIsPremiumRequiredToContact extends Request, Bool[]> { id: Api.TypeInputUser[]; - }; + } } export namespace contacts { @@ -14874,75 +16593,75 @@ namespace Api { hash: long; }>, int[]> { hash: long; - }; - export class GetStatuses extends Request {}; + } + export class GetStatuses extends Request {} export class GetContacts extends Request, contacts.TypeContacts> { hash: long; - }; + } export class ImportContacts extends Request, contacts.TypeImportedContacts> { contacts: Api.TypeInputContact[]; - }; + } export class DeleteContacts extends Request, Api.TypeUpdates> { id: Api.TypeInputUser[]; - }; + } export class DeleteByPhones extends Request, Bool> { phones: string[]; - }; + } export class Block extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; myStoriesFrom?: true; id: Api.TypeInputPeer; - }; + } export class Unblock extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; myStoriesFrom?: true; id: Api.TypeInputPeer; - }; + } export class GetBlocked extends Request, contacts.TypeBlocked> { - // flags: undefined; + // flags: Api.Type; myStoriesFrom?: true; offset: int; limit: int; - }; + } export class Search extends Request, contacts.TypeFound> { q: string; limit: int; - }; + } export class ResolveUsername extends Request, contacts.TypeResolvedPeer> { - // flags: undefined; + // flags: Api.Type; username: string; referer?: string; - }; + } export class GetTopPeers extends Request, contacts.TypeTopPeers> { - // flags: undefined; + // flags: Api.Type; correspondents?: true; botsPm?: true; botsInline?: true; @@ -14969,93 +16688,93 @@ namespace Api { offset: int; limit: int; hash: long; - }; + } export class ResetTopPeerRating extends Request, Bool> { category: Api.TypeTopPeerCategory; peer: Api.TypeInputPeer; - }; - export class ResetSaved extends Request {}; - export class GetSaved extends Request {}; + } + export class ResetSaved extends Request {} + export class GetSaved extends Request {} export class ToggleTopPeers extends Request, Bool> { enabled: Bool; - }; + } export class AddContact extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; addPhonePrivacyException?: true; id: Api.TypeInputUser; firstName: string; lastName: string; phone: string; - }; + } export class AcceptContact extends Request, Api.TypeUpdates> { id: Api.TypeInputUser; - }; + } export class GetLocated extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; background?: true; geoPoint: Api.TypeInputGeoPoint; selfExpires?: int; - }; + } export class BlockFromReplies extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; deleteMessage?: true; deleteHistory?: true; reportSpam?: true; msgId: int; - }; + } export class ResolvePhone extends Request, contacts.TypeResolvedPeer> { phone: string; - }; - export class ExportContactToken extends Request {}; + } + export class ExportContactToken extends Request {} export class ImportContactToken extends Request, Api.TypeUser> { token: string; - }; + } export class EditCloseFriends extends Request, Bool> { id: long[]; - }; + } export class SetBlocked extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; myStoriesFrom?: true; id: Api.TypeInputPeer[]; limit: int; - }; - export class GetBirthdays extends Request {}; + } + export class GetBirthdays extends Request {} } export namespace messages { @@ -15063,9 +16782,9 @@ namespace Api { id: Api.TypeInputMessage[]; }>, messages.TypeMessages> { id: Api.TypeInputMessage[]; - }; + } export class GetDialogs extends Request, messages.TypeDialogs> { - // flags: undefined; + // flags: Api.Type; excludePinned?: true; folderId?: int; offsetDate: int; @@ -15082,7 +16801,7 @@ namespace Api { offsetPeer: Api.TypeInputPeer; limit: int; hash: long; - }; + } export class GetHistory extends Request, messages.TypeMessages> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; q: string; fromId?: Api.TypeInputPeer; @@ -15136,16 +16855,16 @@ namespace Api { maxId: int; minId: int; hash: long; - }; + } export class ReadHistory extends Request, messages.TypeAffectedMessages> { peer: Api.TypeInputPeer; maxId: int; - }; + } export class DeleteHistory extends Request, messages.TypeAffectedHistory> { - // flags: undefined; + // flags: Api.Type; justClear?: true; revoke?: true; peer: Api.TypeInputPeer; maxId: int; minDate?: int; maxDate?: int; - }; + } export class DeleteMessages extends Request, messages.TypeAffectedMessages> { - // flags: undefined; + // flags: Api.Type; revoke?: true; id: int[]; - }; + } export class ReceivedMessages extends Request, Api.TypeReceivedNotifyMessage[]> { maxId: int; - }; + } export class SetTyping extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; topMsgId?: int; action: Api.TypeSendMessageAction; - }; + } export class SendMessage extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; noWebpage?: true; silent?: true; background?: true; @@ -15226,9 +16945,9 @@ namespace Api { sendAs?: Api.TypeInputPeer; quickReplyShortcut?: Api.TypeInputQuickReplyShortcut; effect?: long; - }; + } export class SendMedia extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; silent?: true; background?: true; clearDraft?: true; @@ -15267,9 +16986,9 @@ namespace Api { sendAs?: Api.TypeInputPeer; quickReplyShortcut?: Api.TypeInputQuickReplyShortcut; effect?: long; - }; + } export class ForwardMessages extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; silent?: true; background?: true; withMyScore?: true; @@ -15302,17 +17021,17 @@ namespace Api { scheduleDate?: int; sendAs?: Api.TypeInputPeer; quickReplyShortcut?: Api.TypeInputQuickReplyShortcut; - }; + } export class ReportSpam extends Request, Bool> { peer: Api.TypeInputPeer; - }; + } export class GetPeerSettings extends Request, messages.TypePeerSettings> { peer: Api.TypeInputPeer; - }; + } export class Report extends Request, messages.TypeChats> { id: long[]; - }; + } export class GetFullChat extends Request, messages.TypeChatFull> { chatId: long; - }; + } export class EditChatTitle extends Request, Api.TypeUpdates> { chatId: long; title: string; - }; + } export class EditChatPhoto extends Request, Api.TypeUpdates> { chatId: long; photo: Api.TypeInputChatPhoto; - }; + } export class AddChatUser extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; revokeHistory?: true; chatId: long; userId: Api.TypeInputUser; - }; + } export class CreateChat extends Request, messages.TypeInvitedUsers> { - // flags: undefined; + // flags: Api.Type; users: Api.TypeInputUser[]; title: string; ttlPeriod?: int; - }; + } export class GetDhConfig extends Request, messages.TypeDhConfig> { version: int; randomLength: int; - }; + } export class RequestEncryption extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; deleteHistory?: true; chatId: int; - }; + } export class SetEncryptedTyping extends Request, Bool> { peer: Api.TypeInputEncryptedChat; typing: Bool; - }; + } export class ReadEncryptedHistory extends Request, Bool> { peer: Api.TypeInputEncryptedChat; maxDate: int; - }; + } export class SendEncrypted extends Request, messages.TypeSentEncryptedMessage> { - // flags: undefined; + // flags: Api.Type; silent?: true; peer: Api.TypeInputEncryptedChat; randomId: long; data: bytes; - }; + } export class SendEncryptedFile extends Request, messages.TypeSentEncryptedMessage> { - // flags: undefined; + // flags: Api.Type; silent?: true; peer: Api.TypeInputEncryptedChat; randomId: long; data: bytes; file: Api.TypeInputEncryptedFile; - }; + } export class SendEncryptedService extends Request, long[]> { maxQts: int; - }; + } export class ReportEncryptedSpam extends Request, Bool> { peer: Api.TypeInputEncryptedChat; - }; + } export class ReadMessageContents extends Request, messages.TypeAffectedMessages> { id: int[]; - }; + } export class GetStickers extends Request, messages.TypeStickers> { emoticon: string; hash: long; - }; + } export class GetAllStickers extends Request, messages.TypeAllStickers> { hash: long; - }; + } export class GetWebPagePreview extends Request, messages.TypeWebPagePreview> { - // flags: undefined; + // flags: Api.Type; message: string; entities?: Api.TypeMessageEntity[]; - }; + } export class ExportChatInvite extends Request, Api.TypeExportedChatInvite> { - // flags: undefined; + // flags: Api.Type; legacyRevokePermanent?: true; requestNeeded?: true; peer: Api.TypeInputPeer; @@ -15518,36 +17237,36 @@ namespace Api { usageLimit?: int; title?: string; subscriptionPricing?: Api.TypeStarsSubscriptionPricing; - }; + } export class CheckChatInvite extends Request, Api.TypeChatInvite> { hash: string; - }; + } export class ImportChatInvite extends Request, Api.TypeUpdates> { hash: string; - }; + } export class GetStickerSet extends Request, messages.TypeStickerSet> { stickerset: Api.TypeInputStickerSet; hash: int; - }; + } export class InstallStickerSet extends Request, messages.TypeStickerSetInstallResult> { stickerset: Api.TypeInputStickerSet; archived: Bool; - }; + } export class UninstallStickerSet extends Request, Bool> { stickerset: Api.TypeInputStickerSet; - }; + } export class StartBot extends Request, Api.TypeUpdates> { chatId: long; - }; + } export class SearchGlobal extends Request, messages.TypeMessages> { - // flags: undefined; + // flags: Api.Type; broadcastsOnly?: true; groupsOnly?: true; usersOnly?: true; @@ -15610,18 +17329,18 @@ namespace Api { offsetPeer: Api.TypeInputPeer; offsetId: int; limit: int; - }; + } export class ReorderStickerSets extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; masks?: true; emojis?: true; order: long[]; - }; + } export class GetDocumentByHash extends Request, messages.TypeSavedGifs> { hash: long; - }; + } export class SaveGif extends Request, Bool> { id: Api.TypeInputDocument; unsave: Bool; - }; + } export class GetInlineBotResults extends Request, messages.TypeBotResults> { - // flags: undefined; + // flags: Api.Type; bot: Api.TypeInputUser; peer: Api.TypeInputPeer; geoPoint?: Api.TypeInputGeoPoint; query: string; offset: string; - }; + } export class SetInlineBotResults extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; gallery?: true; private?: true; queryId: long; @@ -15678,9 +17397,9 @@ namespace Api { nextOffset?: string; switchPm?: Api.TypeInlineBotSwitchPM; switchWebview?: Api.TypeInlineBotWebView; - }; + } export class SendInlineBotResult extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; silent?: true; background?: true; clearDraft?: true; @@ -15707,16 +17426,16 @@ namespace Api { scheduleDate?: int; sendAs?: Api.TypeInputPeer; quickReplyShortcut?: Api.TypeInputQuickReplyShortcut; - }; + } export class GetMessageEditData extends Request, messages.TypeMessageEditData> { peer: Api.TypeInputPeer; id: int; - }; + } export class EditMessage extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; noWebpage?: true; invertMedia?: true; peer: Api.TypeInputPeer; @@ -15739,9 +17458,9 @@ namespace Api { entities?: Api.TypeMessageEntity[]; scheduleDate?: int; quickReplyShortcutId?: int; - }; + } export class EditInlineBotMessage extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; noWebpage?: true; invertMedia?: true; id: Api.TypeInputBotInlineMessageID; @@ -15758,44 +17477,44 @@ namespace Api { media?: Api.TypeInputMedia; replyMarkup?: Api.TypeReplyMarkup; entities?: Api.TypeMessageEntity[]; - }; + } export class GetBotCallbackAnswer extends Request, messages.TypeBotCallbackAnswer> { - // flags: undefined; + // flags: Api.Type; game?: true; peer: Api.TypeInputPeer; msgId: int; data?: bytes; password?: Api.TypeInputCheckPasswordSRP; - }; + } export class SetBotCallbackAnswer extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; alert?: true; queryId: long; message?: string; url?: string; cacheTime: int; - }; + } export class GetPeerDialogs extends Request, messages.TypePeerDialogs> { peers: Api.TypeInputDialogPeer[]; - }; + } export class SaveDraft extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; noWebpage?: true; invertMedia?: true; replyTo?: Api.TypeInputReplyTo; @@ -15814,70 +17533,70 @@ namespace Api { entities?: Api.TypeMessageEntity[]; media?: Api.TypeInputMedia; effect?: long; - }; - export class GetAllDrafts extends Request {}; + } + export class GetAllDrafts extends Request {} export class GetFeaturedStickers extends Request, messages.TypeFeaturedStickers> { hash: long; - }; + } export class ReadFeaturedStickers extends Request, Bool> { id: long[]; - }; + } export class GetRecentStickers extends Request, messages.TypeRecentStickers> { - // flags: undefined; + // flags: Api.Type; attached?: true; hash: long; - }; + } export class SaveRecentSticker extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; attached?: true; id: Api.TypeInputDocument; unsave: Bool; - }; + } export class ClearRecentStickers extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; attached?: true; - }; + } export class GetArchivedStickers extends Request, messages.TypeArchivedStickers> { - // flags: undefined; + // flags: Api.Type; masks?: true; emojis?: true; offsetId: long; limit: int; - }; + } export class GetMaskStickers extends Request, messages.TypeAllStickers> { hash: long; - }; + } export class GetAttachedStickers extends Request, Api.TypeStickerSetCovered[]> { media: Api.TypeInputStickeredMedia; - }; + } export class SetGameScore extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; editMessage?: true; force?: true; peer: Api.TypeInputPeer; id: int; userId: Api.TypeInputUser; score: int; - }; + } export class SetInlineGameScore extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; editMessage?: true; force?: true; id: Api.TypeInputBotInlineMessageID; userId: Api.TypeInputUser; score: int; - }; + } export class GetGameHighScores extends Request, messages.TypeHighScores> { id: Api.TypeInputBotInlineMessageID; userId: Api.TypeInputUser; - }; + } export class GetCommonChats extends Request, messages.TypeWebPage> { url: string; hash: int; - }; + } export class ToggleDialogPin extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; pinned?: true; peer: Api.TypeInputDialogPeer; - }; + } export class ReorderPinnedDialogs extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; force?: true; folderId: int; order: Api.TypeInputDialogPeer[]; - }; + } export class GetPinnedDialogs extends Request, messages.TypePeerDialogs> { folderId: int; - }; + } export class SetBotShippingResults extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; queryId: long; error?: string; shippingOptions?: Api.TypeShippingOption[]; - }; + } export class SetBotPrecheckoutResults extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; success?: true; queryId: long; error?: string; - }; + } export class UploadMedia extends Request, Api.TypeMessageMedia> { - // flags: undefined; + // flags: Api.Type; businessConnectionId?: string; peer: Api.TypeInputPeer; media: Api.TypeInputMedia; - }; + } export class SendScreenshotNotification extends Request, messages.TypeFavedStickers> { hash: long; - }; + } export class FaveSticker extends Request, Bool> { id: Api.TypeInputDocument; unfave: Bool; - }; + } export class GetUnreadMentions extends Request, messages.TypeMessages> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; topMsgId?: int; offsetId: int; @@ -16037,16 +17756,16 @@ namespace Api { limit: int; maxId: int; minId: int; - }; + } export class ReadMentions extends Request, messages.TypeAffectedHistory> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; topMsgId?: int; - }; + } export class GetRecentLocations extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; silent?: true; background?: true; clearDraft?: true; @@ -16088,52 +17807,52 @@ namespace Api { sendAs?: Api.TypeInputPeer; quickReplyShortcut?: Api.TypeInputQuickReplyShortcut; effect?: long; - }; + } export class UploadEncryptedFile extends Request, Api.TypeEncryptedFile> { peer: Api.TypeInputEncryptedChat; file: Api.TypeInputEncryptedFile; - }; + } export class SearchStickerSets extends Request, messages.TypeFoundStickerSets> { - // flags: undefined; + // flags: Api.Type; excludeFeatured?: true; q: string; hash: long; - }; - export class GetSplitRanges extends Request {}; + } + export class GetSplitRanges extends Request {} export class MarkDialogUnread extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; unread?: true; peer: Api.TypeInputDialogPeer; - }; - export class GetDialogUnreadMarks extends Request {}; - export class ClearAllDrafts extends Request {}; + } + export class GetDialogUnreadMarks extends Request {} + export class ClearAllDrafts extends Request {} export class UpdatePinnedMessage extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; silent?: true; unpin?: true; pmOneside?: true; peer: Api.TypeInputPeer; id: int; - }; + } export class SendVote extends Request, Api.TypeUpdates> { peer: Api.TypeInputPeer; msgId: int; - }; + } export class GetOnlines extends Request, Api.TypeChatOnlines> { peer: Api.TypeInputPeer; - }; + } export class EditChatAbout extends Request, Bool> { peer: Api.TypeInputPeer; about: string; - }; + } export class EditChatDefaultBannedRights extends Request, Api.TypeUpdates> { peer: Api.TypeInputPeer; bannedRights: Api.TypeChatBannedRights; - }; + } export class GetEmojiKeywords extends Request, Api.TypeEmojiKeywordsDifference> { langCode: string; - }; + } export class GetEmojiKeywordsDifference extends Request, Api.TypeEmojiKeywordsDifference> { langCode: string; fromVersion: int; - }; + } export class GetEmojiKeywordsLanguages extends Request, Api.TypeEmojiLanguage[]> { langCodes: string[]; - }; + } export class GetEmojiURL extends Request, Api.TypeEmojiURL> { langCode: string; - }; + } export class GetSearchCounters extends Request, messages.TypeSearchCounter[]> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; savedPeerId?: Api.TypeInputPeer; topMsgId?: int; filters: Api.TypeMessagesFilter[]; - }; + } export class RequestUrlAuth extends Request, Api.TypeUrlAuthResult> { - // flags: undefined; + // flags: Api.Type; peer?: Api.TypeInputPeer; msgId?: int; buttonId?: int; url?: string; - }; + } export class AcceptUrlAuth extends Request, Api.TypeUrlAuthResult> { - // flags: undefined; + // flags: Api.Type; writeAllowed?: true; peer?: Api.TypeInputPeer; msgId?: int; buttonId?: int; url?: string; - }; + } export class HidePeerSettingsBar extends Request, Bool> { peer: Api.TypeInputPeer; - }; + } export class GetScheduledHistory extends Request, messages.TypeMessages> { peer: Api.TypeInputPeer; hash: long; - }; + } export class GetScheduledMessages extends Request, messages.TypeMessages> { peer: Api.TypeInputPeer; id: int[]; - }; + } export class SendScheduledMessages extends Request, Api.TypeUpdates> { peer: Api.TypeInputPeer; id: int[]; - }; + } export class DeleteScheduledMessages extends Request, Api.TypeUpdates> { peer: Api.TypeInputPeer; id: int[]; - }; + } export class GetPollVotes extends Request, messages.TypeVotesList> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; id: int; option?: bytes; offset?: string; limit: int; - }; + } export class ToggleStickerSets extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; uninstall?: true; archive?: true; unarchive?: true; stickersets: Api.TypeInputStickerSet[]; - }; - export class GetDialogFilters extends Request {}; - export class GetSuggestedDialogFilters extends Request {}; + } + export class GetDialogFilters extends Request {} + export class GetSuggestedDialogFilters extends Request {} export class UpdateDialogFilter extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; id: int; filter?: Api.TypeDialogFilter; - }; + } export class UpdateDialogFiltersOrder extends Request, Bool> { order: int[]; - }; + } export class GetOldFeaturedStickers extends Request, messages.TypeDiscussionMessage> { peer: Api.TypeInputPeer; msgId: int; - }; + } export class ReadDiscussion extends Request, messages.TypeAffectedHistory> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; topMsgId?: int; - }; + } export class DeleteChat extends Request, Bool> { chatId: long; - }; + } export class DeletePhoneCallHistory extends Request, messages.TypeAffectedFoundMessages> { - // flags: undefined; + // flags: Api.Type; revoke?: true; - }; + } export class CheckHistoryImport extends Request, messages.TypeHistoryImportParsed> { importHead: string; - }; + } export class InitHistoryImport extends Request, Bool> { peer: Api.TypeInputPeer; importId: long; - }; + } export class GetExportedChatInvites extends Request, messages.TypeExportedChatInvites> { - // flags: undefined; + // flags: Api.Type; revoked?: true; peer: Api.TypeInputPeer; adminId: Api.TypeInputUser; offsetDate?: int; offsetLink?: string; limit: int; - }; + } export class GetExportedChatInvite extends Request, messages.TypeExportedChatInvite> { peer: Api.TypeInputPeer; link: string; - }; + } export class EditExportedChatInvite extends Request, messages.TypeExportedChatInvite> { - // flags: undefined; + // flags: Api.Type; revoked?: true; peer: Api.TypeInputPeer; link: string; @@ -16450,28 +18169,28 @@ namespace Api { usageLimit?: int; requestNeeded?: Bool; title?: string; - }; + } export class DeleteRevokedExportedChatInvites extends Request, Bool> { peer: Api.TypeInputPeer; adminId: Api.TypeInputUser; - }; + } export class DeleteExportedChatInvite extends Request, Bool> { peer: Api.TypeInputPeer; link: string; - }; + } export class GetAdminsWithInvites extends Request, messages.TypeChatAdminsWithInvites> { peer: Api.TypeInputPeer; - }; + } export class GetChatInviteImporters extends Request, messages.TypeChatInviteImporters> { - // flags: undefined; + // flags: Api.Type; requested?: true; subscriptionExpired?: true; peer: Api.TypeInputPeer; @@ -16490,174 +18209,174 @@ namespace Api { offsetDate: int; offsetUser: Api.TypeInputUser; limit: int; - }; + } export class SetHistoryTTL extends Request, Api.TypeUpdates> { peer: Api.TypeInputPeer; period: int; - }; + } export class CheckHistoryImportPeer extends Request, messages.TypeCheckedHistoryImportPeer> { peer: Api.TypeInputPeer; - }; + } export class SetChatTheme extends Request, Api.TypeUpdates> { peer: Api.TypeInputPeer; emoticon: string; - }; + } export class GetMessageReadParticipants extends Request, Api.TypeReadParticipantDate[]> { peer: Api.TypeInputPeer; msgId: int; - }; + } export class GetSearchResultsCalendar extends Request, messages.TypeSearchResultsCalendar> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; savedPeerId?: Api.TypeInputPeer; filter: Api.TypeMessagesFilter; offsetId: int; offsetDate: int; - }; + } export class GetSearchResultsPositions extends Request, messages.TypeSearchResultsPositions> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; savedPeerId?: Api.TypeInputPeer; filter: Api.TypeMessagesFilter; offsetId: int; limit: int; - }; + } export class HideChatJoinRequest extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; approved?: true; peer: Api.TypeInputPeer; userId: Api.TypeInputUser; - }; + } export class HideAllChatJoinRequests extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; approved?: true; peer: Api.TypeInputPeer; link?: string; - }; + } export class ToggleNoForwards extends Request, Api.TypeUpdates> { peer: Api.TypeInputPeer; enabled: Bool; - }; + } export class SaveDefaultSendAs extends Request, Bool> { peer: Api.TypeInputPeer; sendAs: Api.TypeInputPeer; - }; + } export class SendReaction extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; big?: true; addToRecent?: true; peer: Api.TypeInputPeer; msgId: int; reaction?: Api.TypeReaction[]; - }; + } export class GetMessagesReactions extends Request, Api.TypeUpdates> { peer: Api.TypeInputPeer; id: int[]; - }; + } export class GetMessageReactionsList extends Request, messages.TypeMessageReactionsList> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; id: int; reaction?: Api.TypeReaction; offset?: string; limit: int; - }; + } export class SetChatAvailableReactions extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; availableReactions: Api.TypeChatReactions; reactionsLimit?: int; paidEnabled?: Bool; - }; + } export class GetAvailableReactions extends Request, messages.TypeAvailableReactions> { hash: int; - }; + } export class SetDefaultReaction extends Request, Bool> { reaction: Api.TypeReaction; - }; + } export class TranslateText extends Request, messages.TypeTranslatedText> { - // flags: undefined; + // flags: Api.Type; peer?: Api.TypeInputPeer; id?: int[]; text?: Api.TypeTextWithEntities[]; toLang: string; - }; + } export class GetUnreadReactions extends Request, messages.TypeMessages> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; topMsgId?: int; offsetId: int; @@ -16674,16 +18393,16 @@ namespace Api { limit: int; maxId: int; minId: int; - }; + } export class ReadReactions extends Request, messages.TypeAffectedHistory> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; topMsgId?: int; - }; + } export class SearchSentMedia extends Request, Api.TypeAttachMenuBots> { hash: long; - }; + } export class GetAttachMenuBot extends Request, Api.TypeAttachMenuBotsBot> { bot: Api.TypeInputUser; - }; + } export class ToggleBotInAttachMenu extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; writeAllowed?: true; bot: Api.TypeInputUser; enabled: Bool; - }; + } export class RequestWebView extends Request, Api.TypeWebViewResult> { - // flags: undefined; + // flags: Api.Type; fromBotMenu?: true; silent?: true; compact?: true; @@ -16742,9 +18461,9 @@ namespace Api { platform: string; replyTo?: Api.TypeInputReplyTo; sendAs?: Api.TypeInputPeer; - }; + } export class ProlongWebView extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; silent?: true; peer: Api.TypeInputPeer; bot: Api.TypeInputUser; queryId: long; replyTo?: Api.TypeInputReplyTo; sendAs?: Api.TypeInputPeer; - }; + } export class RequestSimpleWebView extends Request, Api.TypeWebViewResult> { - // flags: undefined; + // flags: Api.Type; fromSwitchWebview?: true; fromSideMenu?: true; compact?: true; @@ -16782,14 +18501,14 @@ namespace Api { startParam?: string; themeParams?: Api.TypeDataJSON; platform: string; - }; + } export class SendWebViewResultMessage extends Request, Api.TypeWebViewMessageSent> { botQueryId: string; result: Api.TypeInputBotInlineResult; - }; + } export class SendWebViewData extends Request, messages.TypeTranscribedAudio> { peer: Api.TypeInputPeer; msgId: int; - }; + } export class RateTranscribedAudio extends Request, Api.TypeDocument[]> { documentId: long[]; - }; + } export class GetEmojiStickers extends Request, messages.TypeAllStickers> { hash: long; - }; + } export class GetFeaturedEmojiStickers extends Request, messages.TypeFeaturedStickers> { hash: long; - }; + } export class ReportReaction extends Request, messages.TypeReactions> { limit: int; hash: long; - }; + } export class GetRecentReactions extends Request, messages.TypeReactions> { limit: int; hash: long; - }; - export class ClearRecentReactions extends Request {}; + } + export class ClearRecentReactions extends Request {} export class GetExtendedMedia extends Request, Api.TypeUpdates> { peer: Api.TypeInputPeer; id: int[]; - }; + } export class SetDefaultHistoryTTL extends Request, Bool> { period: int; - }; - export class GetDefaultHistoryTTL extends Request {}; + } + export class GetDefaultHistoryTTL extends Request {} export class SendBotRequestedPeer extends Request, messages.TypeEmojiGroups> { hash: int; - }; + } export class GetEmojiStatusGroups extends Request, messages.TypeEmojiGroups> { hash: int; - }; + } export class GetEmojiProfilePhotoGroups extends Request, messages.TypeEmojiGroups> { hash: int; - }; + } export class SearchCustomEmoji extends Request, Api.TypeEmojiList> { emoticon: string; hash: long; - }; + } export class TogglePeerTranslations extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; disabled?: true; peer: Api.TypeInputPeer; - }; + } export class GetBotApp extends Request, messages.TypeBotApp> { app: Api.TypeInputBotApp; hash: long; - }; + } export class RequestAppWebView extends Request, Api.TypeWebViewResult> { - // flags: undefined; + // flags: Api.Type; writeAllowed?: true; compact?: true; fullscreen?: true; @@ -16940,9 +18659,9 @@ namespace Api { startParam?: string; themeParams?: Api.TypeDataJSON; platform: string; - }; + } export class SetChatWallPaper extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; forBoth?: true; revert?: true; peer: Api.TypeInputPeer; wallpaper?: Api.TypeInputWallPaper; settings?: Api.TypeWallPaperSettings; id?: int; - }; + } export class SearchEmojiStickerSets extends Request, messages.TypeFoundStickerSets> { - // flags: undefined; + // flags: Api.Type; excludeFeatured?: true; q: string; hash: long; - }; + } export class GetSavedDialogs extends Request, messages.TypeSavedDialogs> { - // flags: undefined; + // flags: Api.Type; excludePinned?: true; offsetDate: int; offsetId: int; offsetPeer: Api.TypeInputPeer; limit: int; hash: long; - }; + } export class GetSavedHistory extends Request, messages.TypeAffectedHistory> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; maxId: int; minDate?: int; maxDate?: int; - }; - export class GetPinnedSavedDialogs extends Request {}; + } + export class GetPinnedSavedDialogs extends Request {} export class ToggleSavedDialogPin extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; pinned?: true; peer: Api.TypeInputDialogPeer; - }; + } export class ReorderPinnedSavedDialogs extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; force?: true; order: Api.TypeInputDialogPeer[]; - }; + } export class GetSavedReactionTags extends Request, messages.TypeSavedReactionTags> { - // flags: undefined; + // flags: Api.Type; peer?: Api.TypeInputPeer; hash: long; - }; + } export class UpdateSavedReactionTag extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; reaction: Api.TypeReaction; title?: string; - }; + } export class GetDefaultTagReactions extends Request, messages.TypeReactions> { hash: long; - }; + } export class GetOutboxReadDate extends Request, Api.TypeOutboxReadDate> { peer: Api.TypeInputPeer; msgId: int; - }; + } export class GetQuickReplies extends Request, messages.TypeQuickReplies> { hash: long; - }; + } export class ReorderQuickReplies extends Request, Bool> { order: int[]; - }; + } export class CheckQuickReplyShortcut extends Request, Bool> { shortcut: string; - }; + } export class EditQuickReplyShortcut extends Request, Bool> { shortcutId: int; shortcut: string; - }; + } export class DeleteQuickReplyShortcut extends Request, Bool> { shortcutId: int; - }; + } export class GetQuickReplyMessages extends Request, messages.TypeMessages> { - // flags: undefined; + // flags: Api.Type; shortcutId: int; id?: int[]; hash: long; - }; + } export class SendQuickReplyMessages extends Request, Api.TypeUpdates> { shortcutId: int; id: int[]; - }; + } export class ToggleDialogFilterTags extends Request, Bool> { enabled: Bool; - }; + } export class GetMyStickers extends Request, messages.TypeMyStickers> { offsetId: long; limit: int; - }; + } export class GetEmojiStickerGroups extends Request, messages.TypeEmojiGroups> { hash: int; - }; + } export class GetAvailableEffects extends Request, messages.TypeAvailableEffects> { hash: int; - }; + } export class EditFactCheck extends Request, Api.TypeUpdates> { peer: Api.TypeInputPeer; msgId: int; - }; + } export class GetFactCheck extends Request, Api.TypeFactCheck[]> { peer: Api.TypeInputPeer; msgId: int[]; - }; + } export class RequestMainWebView extends Request, Api.TypeWebViewResult> { - // flags: undefined; + // flags: Api.Type; compact?: true; fullscreen?: true; peer: Api.TypeInputPeer; @@ -17186,22 +18905,22 @@ namespace Api { startParam?: string; themeParams?: Api.TypeDataJSON; platform: string; - }; + } export class SendPaidReaction extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; msgId: int; count: int; randomId: long; private?: Bool; - }; + } export class TogglePaidReactionPrivacy extends Request {}; + } + export class GetPaidReactionPrivacy extends Request {} export class ViewSponsoredMessage extends Request, Bool> { peer: Api.TypeInputPeer; randomId: bytes; - }; + } export class ClickSponsoredMessage extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; media?: true; fullscreen?: true; peer: Api.TypeInputPeer; randomId: bytes; - }; + } export class ReportSponsoredMessage extends Request, messages.TypeSponsoredMessages> { peer: Api.TypeInputPeer; - }; + } export class SavePreparedInlineMessage extends Request, messages.TypeBotPreparedInlineMessage> { - // flags: undefined; + // flags: Api.Type; result: Api.TypeInputBotInlineResult; userId: Api.TypeInputUser; peerTypes?: Api.TypeInlineQueryPeerType[]; - }; + } export class GetPreparedInlineMessage extends Request, messages.TypePreparedInlineMessage> { bot: Api.TypeInputUser; id: string; - }; + } export class SearchStickers extends Request, messages.TypeFoundStickers> { - // flags: undefined; + // flags: Api.Type; emojis?: true; q: string; emoticon: string; @@ -17282,24 +19001,24 @@ namespace Api { offset: int; limit: int; hash: long; - }; + } export class ReportMessagesDelivery extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; push?: true; peer: Api.TypeInputPeer; id: int[]; - }; + } } export namespace updates { - export class GetState extends Request {}; + export class GetState extends Request {} export class GetDifference extends Request, updates.TypeDifference> { - // flags: undefined; + // flags: Api.Type; pts: int; ptsLimit?: int; ptsTotalLimit?: int; date: int; qts: int; qtsLimit?: int; - }; + } export class GetChannelDifference extends Request, updates.TypeChannelDifference> { - // flags: undefined; + // flags: Api.Type; force?: true; channel: Api.TypeInputChannel; filter: Api.TypeChannelMessagesFilter; pts: int; limit: int; - }; + } } export namespace photos { export class UpdateProfilePhoto extends Request, photos.TypePhoto> { - // flags: undefined; + // flags: Api.Type; fallback?: true; bot?: Api.TypeInputUser; id: Api.TypeInputPhoto; - }; + } export class UploadProfilePhoto extends Request, photos.TypePhoto> { - // flags: undefined; + // flags: Api.Type; fallback?: true; bot?: Api.TypeInputUser; file?: Api.TypeInputFile; video?: Api.TypeInputFile; videoStartTs?: double; videoEmojiMarkup?: Api.TypeVideoSize; - }; + } export class DeletePhotos extends Request, long[]> { id: Api.TypeInputPhoto[]; - }; + } export class GetUserPhotos extends Request, photos.TypePhoto> { - // flags: undefined; + // flags: Api.Type; suggest?: true; save?: true; userId: Api.TypeInputUser; @@ -17395,7 +19114,7 @@ namespace Api { video?: Api.TypeInputFile; videoStartTs?: double; videoEmojiMarkup?: Api.TypeVideoSize; - }; + } } export namespace upload { @@ -17407,22 +19126,22 @@ namespace Api { fileId: long; filePart: int; bytes: bytes; - }; + } export class GetFile extends Request, upload.TypeFile> { - // flags: undefined; + // flags: Api.Type; precise?: true; cdnSupported?: true; location: Api.TypeInputFileLocation; offset: long; limit: int; - }; + } export class SaveBigFilePart extends Request, Api.TypeFileHash[]> { fileToken: bytes; requestToken: bytes; - }; + } export class GetCdnFileHashes extends Request, Api.TypeFileHash[]> { fileToken: bytes; offset: long; - }; + } export class GetFileHashes extends Request, Api.TypeFileHash[]> { location: Api.TypeInputFileLocation; offset: long; - }; + } } export namespace help { - export class GetConfig extends Request {}; - export class GetNearestDc extends Request {}; + export class GetConfig extends Request {} + export class GetNearestDc extends Request {} export class GetAppUpdate extends Request, help.TypeAppUpdate> { source: string; - }; - export class GetInviteText extends Request {}; - export class GetSupport extends Request {}; + } + export class GetInviteText extends Request {} + export class GetSupport extends Request {} export class SetBotUpdatesStatus extends Request, Bool> { pendingUpdatesCount: int; message: string; - }; - export class GetCdnConfig extends Request {}; + } + export class GetCdnConfig extends Request {} export class GetRecentMeUrls extends Request, help.TypeRecentMeUrls> { referer: string; - }; - export class GetTermsOfServiceUpdate extends Request {}; + } + export class GetTermsOfServiceUpdate extends Request {} export class AcceptTermsOfService extends Request, Bool> { id: Api.TypeDataJSON; - }; + } export class GetDeepLinkInfo extends Request, help.TypeDeepLinkInfo> { path: string; - }; + } export class GetAppConfig extends Request, help.TypeAppConfig> { hash: int; - }; + } export class SaveAppLog extends Request, Bool> { events: Api.TypeInputAppEvent[]; - }; + } export class GetPassportConfig extends Request, help.TypePassportConfig> { hash: int; - }; - export class GetSupportName extends Request {}; + } + export class GetSupportName extends Request {} export class GetUserInfo extends Request, help.TypeUserInfo> { userId: Api.TypeInputUser; - }; + } export class EditUserInfo extends Request {}; + } + export class GetPromoData extends Request {} export class HidePromoData extends Request, Bool> { peer: Api.TypeInputPeer; - }; + } export class DismissSuggestion extends Request, Bool> { peer: Api.TypeInputPeer; suggestion: string; - }; + } export class GetCountriesList extends Request, help.TypeCountriesList> { langCode: string; hash: int; - }; - export class GetPremiumPromo extends Request {}; + } + export class GetPremiumPromo extends Request {} export class GetPeerColors extends Request, help.TypePeerColors> { hash: int; - }; + } export class GetPeerProfileColors extends Request, help.TypePeerColors> { hash: int; - }; + } export class GetTimezonesList extends Request, help.TypeTimezonesList> { hash: int; - }; + } } export namespace channels { @@ -17584,14 +19303,14 @@ namespace Api { }>, Bool> { channel: Api.TypeInputChannel; maxId: int; - }; + } export class DeleteMessages extends Request, messages.TypeAffectedMessages> { channel: Api.TypeInputChannel; id: int[]; - }; + } export class ReportSpam extends Request, messages.TypeMessages> { channel: Api.TypeInputChannel; id: Api.TypeInputMessage[]; - }; + } export class GetParticipants extends Request, channels.TypeChannelParticipant> { channel: Api.TypeInputChannel; participant: Api.TypeInputPeer; - }; + } export class GetChannels extends Request, messages.TypeChats> { id: Api.TypeInputChannel[]; - }; + } export class GetFullChannel extends Request, messages.TypeChatFull> { channel: Api.TypeInputChannel; - }; + } export class CreateChannel extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; broadcast?: true; megagroup?: true; forImport?: true; @@ -17660,7 +19379,7 @@ namespace Api { geoPoint?: Api.TypeInputGeoPoint; address?: string; ttlPeriod?: int; - }; + } export class EditAdmin extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; title: string; - }; + } export class EditPhoto extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; photo: Api.TypeInputChatPhoto; - }; + } export class CheckUsername extends Request, Bool> { channel: Api.TypeInputChannel; username: string; - }; + } export class UpdateUsername extends Request, Bool> { channel: Api.TypeInputChannel; username: string; - }; + } export class JoinChannel extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; - }; + } export class LeaveChannel extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; - }; + } export class InviteToChannel extends Request, messages.TypeInvitedUsers> { channel: Api.TypeInputChannel; users: Api.TypeInputUser[]; - }; + } export class DeleteChannel extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; - }; + } export class ExportMessageLink extends Request, Api.TypeExportedMessageLink> { - // flags: undefined; + // flags: Api.Type; grouped?: true; thread?: true; channel: Api.TypeInputChannel; id: int; - }; + } export class ToggleSignatures extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; signaturesEnabled?: true; profilesEnabled?: true; channel: Api.TypeInputChannel; - }; + } export class GetAdminedPublicChannels extends Request, messages.TypeChats> { - // flags: undefined; + // flags: Api.Type; byLocation?: true; checkLimit?: true; forPersonal?: true; - }; + } export class EditBanned extends Request, channels.TypeAdminLogResults> { - // flags: undefined; + // flags: Api.Type; channel: Api.TypeInputChannel; q: string; eventsFilter?: Api.TypeChannelAdminLogEventsFilter; @@ -17784,52 +19503,52 @@ namespace Api { maxId: long; minId: long; limit: int; - }; + } export class SetStickers extends Request, Bool> { channel: Api.TypeInputChannel; stickerset: Api.TypeInputStickerSet; - }; + } export class ReadMessageContents extends Request, Bool> { channel: Api.TypeInputChannel; id: int[]; - }; + } export class DeleteHistory extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; forEveryone?: true; channel: Api.TypeInputChannel; maxId: int; - }; + } export class TogglePreHistoryHidden extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; enabled: Bool; - }; + } export class GetLeftChannels extends Request, messages.TypeChats> { offset: int; - }; - export class GetGroupsForDiscussion extends Request {}; + } + export class GetGroupsForDiscussion extends Request {} export class SetDiscussionGroup extends Request, Bool> { broadcast: Api.TypeInputChannel; group: Api.TypeInputChannel; - }; + } export class EditCreator extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; seconds: int; - }; - export class GetInactiveChannels extends Request {}; + } + export class GetInactiveChannels extends Request {} export class ConvertToGigagroup extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; - }; + } export class GetSendAs extends Request, channels.TypeSendAsPeers> { peer: Api.TypeInputPeer; - }; + } export class DeleteParticipantHistory extends Request, messages.TypeAffectedHistory> { channel: Api.TypeInputChannel; participant: Api.TypeInputPeer; - }; + } export class ToggleJoinToSend extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; enabled: Bool; - }; + } export class ToggleJoinRequest extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; enabled: Bool; - }; + } export class ReorderUsernames extends Request, Bool> { channel: Api.TypeInputChannel; order: string[]; - }; + } export class ToggleUsername extends Request, Bool> { channel: Api.TypeInputChannel; - }; + } export class ToggleForum extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; enabled: Bool; - }; + } export class CreateForumTopic extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; channel: Api.TypeInputChannel; title: string; iconColor?: int; iconEmojiId?: long; randomId: long; sendAs?: Api.TypeInputPeer; - }; + } export class GetForumTopics extends Request, messages.TypeForumTopics> { - // flags: undefined; + // flags: Api.Type; channel: Api.TypeInputChannel; q?: string; offsetDate: int; offsetId: int; offsetTopic: int; limit: int; - }; + } export class GetForumTopicsByID extends Request, messages.TypeForumTopics> { channel: Api.TypeInputChannel; topics: int[]; - }; + } export class EditForumTopic extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; channel: Api.TypeInputChannel; topicId: int; title?: string; iconEmojiId?: long; closed?: Bool; hidden?: Bool; - }; + } export class UpdatePinnedForumTopic extends Request, messages.TypeAffectedHistory> { channel: Api.TypeInputChannel; topMsgId: int; - }; + } export class ReorderPinnedForumTopics extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; force?: true; channel: Api.TypeInputChannel; order: int[]; - }; + } export class ToggleAntiSpam extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; enabled: Bool; - }; + } export class ReportAntiSpamFalsePositive extends Request, Bool> { channel: Api.TypeInputChannel; msgId: int; - }; + } export class ToggleParticipantsHidden extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; enabled: Bool; - }; + } export class UpdateColor extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; forProfile?: true; channel: Api.TypeInputChannel; color?: int; backgroundEmojiId?: long; - }; + } export class ToggleViewForumAsMessages extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; enabled: Bool; - }; + } export class GetChannelRecommendations extends Request, messages.TypeChats> { - // flags: undefined; + // flags: Api.Type; channel?: Api.TypeInputChannel; - }; + } export class UpdateEmojiStatus extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; emojiStatus: Api.TypeEmojiStatus; - }; + } export class SetBoostsToUnblockRestrictions extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; boosts: int; - }; + } export class SetEmojiStickers extends Request, Bool> { channel: Api.TypeInputChannel; stickerset: Api.TypeInputStickerSet; - }; + } export class RestrictSponsoredMessages extends Request, Api.TypeUpdates> { channel: Api.TypeInputChannel; restricted: Bool; - }; + } export class SearchPosts extends Request, Api.TypeDataJSON> { customMethod: string; params: Api.TypeDataJSON; - }; + } export class AnswerWebhookJSONQuery extends Request, Bool> { queryId: long; data: Api.TypeDataJSON; - }; + } export class SetBotCommands extends Request, Bool> { scope: Api.TypeBotCommandScope; langCode: string; - }; + } export class GetBotCommands extends Request, Api.TypeBotCommand[]> { scope: Api.TypeBotCommandScope; langCode: string; - }; + } export class SetBotMenuButton extends Request, Bool> { userId: Api.TypeInputUser; button: Api.TypeBotMenuButton; - }; + } export class GetBotMenuButton extends Request, Api.TypeBotMenuButton> { userId: Api.TypeInputUser; - }; + } export class SetBotBroadcastDefaultAdminRights extends Request, Bool> { adminRights: Api.TypeChatAdminRights; - }; + } export class SetBotGroupDefaultAdminRights extends Request, Bool> { adminRights: Api.TypeChatAdminRights; - }; + } export class SetBotInfo extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; bot?: Api.TypeInputUser; langCode: string; name?: string; about?: string; description?: string; - }; + } export class GetBotInfo extends Request, bots.TypeBotInfo> { - // flags: undefined; + // flags: Api.Type; bot?: Api.TypeInputUser; langCode: string; - }; + } export class ReorderUsernames extends Request, Bool> { bot: Api.TypeInputUser; order: string[]; - }; + } export class ToggleUsername extends Request, Bool> { bot: Api.TypeInputUser; - }; + } export class AllowSendMessage extends Request, Api.TypeUpdates> { bot: Api.TypeInputUser; - }; + } export class InvokeWebViewCustomMethod extends Request, bots.TypePopularAppBots> { offset: string; limit: int; - }; + } export class AddPreviewMedia extends Request, bots.TypePreviewInfo> { bot: Api.TypeInputUser; langCode: string; - }; + } export class GetPreviewMedias extends Request, Api.TypeBotPreviewMedia[]> { bot: Api.TypeInputUser; - }; + } export class UpdateUserEmojiStatus extends Request, Bool> { userId: Api.TypeInputUser; emojiStatus: Api.TypeEmojiStatus; - }; + } export class ToggleUserEmojiStatusPermission extends Request, Bool> { bot: Api.TypeInputUser; enabled: Bool; - }; + } export class CheckDownloadFileParams extends Request {}; + } + export class GetAdminedBots extends Request {} export class UpdateStarRefProgram extends Request, Api.TypeStarRefProgram> { - // flags: undefined; + // flags: Api.Type; bot: Api.TypeInputUser; commissionPermille: int; durationMonths?: int; - }; + } export class SetCustomVerification extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; enabled?: true; bot?: Api.TypeInputUser; peer: Api.TypeInputPeer; customDescription?: string; - }; + } export class GetBotRecommendations extends Request, users.TypeUsers> { bot: Api.TypeInputUser; - }; + } } export namespace payments { export class GetPaymentForm extends Request, payments.TypePaymentForm> { - // flags: undefined; + // flags: Api.Type; invoice: Api.TypeInputInvoice; themeParams?: Api.TypeDataJSON; - }; + } export class GetPaymentReceipt extends Request, payments.TypePaymentReceipt> { peer: Api.TypeInputPeer; msgId: int; - }; + } export class ValidateRequestedInfo extends Request, payments.TypeValidatedRequestedInfo> { - // flags: undefined; + // flags: Api.Type; save?: true; invoice: Api.TypeInputInvoice; info: Api.TypePaymentRequestedInfo; - }; + } export class SendPaymentForm extends Request, payments.TypePaymentResult> { - // flags: undefined; + // flags: Api.Type; formId: long; invoice: Api.TypeInputInvoice; requestedInfoId?: string; shippingOptionId?: string; credentials: Api.TypeInputPaymentCredentials; tipAmount?: long; - }; - export class GetSavedInfo extends Request {}; + } + export class GetSavedInfo extends Request {} export class ClearSavedInfo extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; credentials?: true; info?: true; - }; + } export class GetBankCardData extends Request, payments.TypeBankCardData> { number: string; - }; + } export class ExportInvoice extends Request, payments.TypeExportedInvoice> { invoiceMedia: Api.TypeInputMedia; - }; + } export class AssignAppStoreTransaction extends Request, Api.TypeUpdates> { receipt: bytes; purpose: Api.TypeInputStorePaymentPurpose; - }; + } export class AssignPlayMarketTransaction extends Request, Api.TypeUpdates> { receipt: Api.TypeDataJSON; purpose: Api.TypeInputStorePaymentPurpose; - }; + } export class CanPurchasePremium extends Request, Bool> { purpose: Api.TypeInputStorePaymentPurpose; - }; + } export class GetPremiumGiftCodeOptions extends Request, Api.TypePremiumGiftCodeOption[]> { - // flags: undefined; + // flags: Api.Type; boostPeer?: Api.TypeInputPeer; - }; + } export class CheckGiftCode extends Request, payments.TypeCheckedGiftCode> { slug: string; - }; + } export class ApplyGiftCode extends Request, Api.TypeUpdates> { slug: string; - }; + } export class GetGiveawayInfo extends Request, payments.TypeGiveawayInfo> { peer: Api.TypeInputPeer; msgId: int; - }; + } export class LaunchPrepaidGiveaway extends Request {}; + } + export class GetStarsTopupOptions extends Request {} export class GetStarsStatus extends Request, payments.TypeStarsStatus> { peer: Api.TypeInputPeer; - }; + } export class GetStarsTransactions extends Request, payments.TypeStarsStatus> { - // flags: undefined; + // flags: Api.Type; inbound?: true; outbound?: true; ascending?: true; @@ -18463,30 +20182,30 @@ namespace Api { peer: Api.TypeInputPeer; offset: string; limit: int; - }; + } export class SendStarsForm extends Request, payments.TypePaymentResult> { formId: long; invoice: Api.TypeInputInvoice; - }; + } export class RefundStarsCharge extends Request, Api.TypeUpdates> { userId: Api.TypeInputUser; chargeId: string; - }; + } export class GetStarsRevenueStats extends Request, payments.TypeStarsRevenueStats> { - // flags: undefined; + // flags: Api.Type; dark?: true; peer: Api.TypeInputPeer; - }; + } export class GetStarsRevenueWithdrawalUrl extends Request, payments.TypeStarsRevenueAdsAccountUrl> { peer: Api.TypeInputPeer; - }; + } export class GetStarsTransactionsByID extends Request, payments.TypeStarsStatus> { peer: Api.TypeInputPeer; id: Api.TypeInputStarsTransaction[]; - }; + } export class GetStarsGiftOptions extends Request, Api.TypeStarsGiftOption[]> { - // flags: undefined; + // flags: Api.Type; userId?: Api.TypeInputUser; - }; + } export class GetStarsSubscriptions extends Request, payments.TypeStarsStatus> { - // flags: undefined; + // flags: Api.Type; missingBalance?: true; peer: Api.TypeInputPeer; offset: string; - }; + } export class ChangeStarsSubscription extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; subscriptionId: string; canceled?: Bool; - }; + } export class FulfillStarsSubscription extends Request, Bool> { peer: Api.TypeInputPeer; subscriptionId: string; - }; - export class GetStarsGiveawayOptions extends Request {}; + } + export class GetStarsGiveawayOptions extends Request {} export class GetStarGifts extends Request, payments.TypeStarGifts> { hash: int; - }; + } export class GetUserStarGifts extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; unsave?: true; msgId: int; - }; + } export class ConvertStarGift extends Request, Bool> { msgId: int; - }; + } export class BotCancelStarsSubscription extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; restore?: true; userId: Api.TypeInputUser; chargeId: string; - }; + } export class GetConnectedStarRefBots extends Request, payments.TypeConnectedStarRefBots> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; offsetDate?: int; offsetLink?: string; limit: int; - }; + } export class GetConnectedStarRefBot extends Request, payments.TypeConnectedStarRefBots> { peer: Api.TypeInputPeer; bot: Api.TypeInputUser; - }; + } export class GetSuggestedStarRefBots extends Request, payments.TypeSuggestedStarRefBots> { - // flags: undefined; + // flags: Api.Type; orderByRevenue?: true; orderByDate?: true; peer: Api.TypeInputPeer; offset: string; limit: int; - }; + } export class ConnectStarRefBot extends Request, payments.TypeConnectedStarRefBots> { peer: Api.TypeInputPeer; bot: Api.TypeInputUser; - }; + } export class EditConnectedStarRefBot extends Request, payments.TypeConnectedStarRefBots> { - // flags: undefined; + // flags: Api.Type; revoked?: true; peer: Api.TypeInputPeer; link: string; - }; + } export class GetStarGiftUpgradePreview extends Request, payments.TypeStarGiftUpgradePreview> { giftId: long; - }; + } export class UpgradeStarGift extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; keepOriginalDetails?: true; msgId: int; - }; + } export class TransferStarGift extends Request, Api.TypeUpdates> { msgId: int; toId: Api.TypeInputUser; - }; + } export class GetUserStarGift extends Request, payments.TypeUserStarGifts> { msgId: int[]; - }; + } export class GetUniqueStarGift extends Request, payments.TypeUniqueStarGift> { slug: string; - }; + } } export namespace stickers { export class CreateStickerSet extends Request, messages.TypeStickerSet> { - // flags: undefined; + // flags: Api.Type; masks?: true; emojis?: true; textColor?: true; @@ -18693,85 +20412,85 @@ namespace Api { thumb?: Api.TypeInputDocument; stickers: Api.TypeInputStickerSetItem[]; software?: string; - }; + } export class RemoveStickerFromSet extends Request, messages.TypeStickerSet> { sticker: Api.TypeInputDocument; - }; + } export class ChangeStickerPosition extends Request, messages.TypeStickerSet> { sticker: Api.TypeInputDocument; position: int; - }; + } export class AddStickerToSet extends Request, messages.TypeStickerSet> { stickerset: Api.TypeInputStickerSet; sticker: Api.TypeInputStickerSetItem; - }; + } export class SetStickerSetThumb extends Request, messages.TypeStickerSet> { - // flags: undefined; + // flags: Api.Type; stickerset: Api.TypeInputStickerSet; thumb?: Api.TypeInputDocument; thumbDocumentId?: long; - }; + } export class CheckShortName extends Request, Bool> { shortName: string; - }; + } export class SuggestShortName extends Request, stickers.TypeSuggestedShortName> { title: string; - }; + } export class ChangeSticker extends Request, messages.TypeStickerSet> { - // flags: undefined; + // flags: Api.Type; sticker: Api.TypeInputDocument; emoji?: string; maskCoords?: Api.TypeMaskCoords; keywords?: string; - }; + } export class RenameStickerSet extends Request, messages.TypeStickerSet> { stickerset: Api.TypeInputStickerSet; title: string; - }; + } export class DeleteStickerSet extends Request, Bool> { stickerset: Api.TypeInputStickerSet; - }; + } export class ReplaceSticker extends Request, messages.TypeStickerSet> { sticker: Api.TypeInputDocument; newSticker: Api.TypeInputStickerSetItem; - }; + } } export namespace phone { - export class GetCallConfig extends Request {}; + export class GetCallConfig extends Request {} export class RequestCall extends Request, phone.TypePhoneCall> { - // flags: undefined; + // flags: Api.Type; video?: true; userId: Api.TypeInputUser; conferenceCall?: Api.TypeInputGroupCall; randomId: int; gAHash: bytes; protocol: Api.TypePhoneCallProtocol; - }; + } export class AcceptCall extends Request, Bool> { peer: Api.TypeInputPhoneCall; - }; + } export class DiscardCall extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; video?: true; peer: Api.TypeInputPhoneCall; duration: int; reason: Api.TypePhoneCallDiscardReason; connectionId: long; - }; + } export class SetCallRating extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; userInitiative?: true; peer: Api.TypeInputPhoneCall; rating: int; comment: string; - }; + } export class SaveCallDebug extends Request, Bool> { peer: Api.TypeInputPhoneCall; debug: Api.TypeDataJSON; - }; + } export class SendSignalingData extends Request, Bool> { peer: Api.TypeInputPhoneCall; data: bytes; - }; + } export class CreateGroupCall extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; rtmpStream?: true; peer: Api.TypeInputPeer; randomId: int; title?: string; scheduleDate?: int; - }; + } export class JoinGroupCall extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; muted?: true; videoStopped?: true; call: Api.TypeInputGroupCall; @@ -18887,44 +20606,44 @@ namespace Api { inviteHash?: string; keyFingerprint?: long; params: Api.TypeDataJSON; - }; + } export class LeaveGroupCall extends Request, Api.TypeUpdates> { call: Api.TypeInputGroupCall; source: int; - }; + } export class InviteToGroupCall extends Request, Api.TypeUpdates> { call: Api.TypeInputGroupCall; users: Api.TypeInputUser[]; - }; + } export class DiscardGroupCall extends Request, Api.TypeUpdates> { call: Api.TypeInputGroupCall; - }; + } export class ToggleGroupCallSettings extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; resetInviteHash?: true; call: Api.TypeInputGroupCall; joinMuted?: Bool; - }; + } export class GetGroupCall extends Request, phone.TypeGroupCall> { call: Api.TypeInputGroupCall; limit: int; - }; + } export class GetGroupParticipants extends Request, int[]> { call: Api.TypeInputGroupCall; sources: int[]; - }; + } export class ToggleGroupCallRecord extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; start?: true; video?: true; call: Api.TypeInputGroupCall; title?: string; videoPortrait?: Bool; - }; + } export class EditGroupCallParticipant extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; call: Api.TypeInputGroupCall; participant: Api.TypeInputPeer; muted?: Bool; @@ -18980,85 +20699,85 @@ namespace Api { videoStopped?: Bool; videoPaused?: Bool; presentationPaused?: Bool; - }; + } export class EditGroupCallTitle extends Request, Api.TypeUpdates> { call: Api.TypeInputGroupCall; title: string; - }; + } export class GetGroupCallJoinAs extends Request, phone.TypeJoinAsPeers> { peer: Api.TypeInputPeer; - }; + } export class ExportGroupCallInvite extends Request, phone.TypeExportedGroupCallInvite> { - // flags: undefined; + // flags: Api.Type; canSelfUnmute?: true; call: Api.TypeInputGroupCall; - }; + } export class ToggleGroupCallStartSubscription extends Request, Api.TypeUpdates> { call: Api.TypeInputGroupCall; subscribed: Bool; - }; + } export class StartScheduledGroupCall extends Request, Api.TypeUpdates> { call: Api.TypeInputGroupCall; - }; + } export class SaveDefaultGroupCallJoinAs extends Request, Bool> { peer: Api.TypeInputPeer; joinAs: Api.TypeInputPeer; - }; + } export class JoinGroupCallPresentation extends Request, Api.TypeUpdates> { call: Api.TypeInputGroupCall; params: Api.TypeDataJSON; - }; + } export class LeaveGroupCallPresentation extends Request, Api.TypeUpdates> { call: Api.TypeInputGroupCall; - }; + } export class GetGroupCallStreamChannels extends Request, phone.TypeGroupCallStreamChannels> { call: Api.TypeInputGroupCall; - }; + } export class GetGroupCallStreamRtmpUrl extends Request, phone.TypeGroupCallStreamRtmpUrl> { peer: Api.TypeInputPeer; revoke: Bool; - }; + } export class SaveCallLog extends Request, Bool> { peer: Api.TypeInputPhoneCall; file: Api.TypeInputFile; - }; + } export class CreateConferenceCall extends Request, phone.TypePhoneCall> { peer: Api.TypeInputPhoneCall; keyFingerprint: long; - }; + } } export namespace langpack { @@ -19068,7 +20787,7 @@ namespace Api { }>, Api.TypeLangPackDifference> { langPack: string; langCode: string; - }; + } export class GetStrings extends Request, Api.TypeLangPackLanguage[]> { langPack: string; - }; + } export class GetLanguage extends Request, Api.TypeLangPackLanguage> { langPack: string; langCode: string; - }; + } } export namespace folders { @@ -19106,37 +20825,37 @@ namespace Api { folderPeers: Api.TypeInputFolderPeer[]; }>, Api.TypeUpdates> { folderPeers: Api.TypeInputFolderPeer[]; - }; + } } export namespace stats { export class GetBroadcastStats extends Request, stats.TypeBroadcastStats> { - // flags: undefined; + // flags: Api.Type; dark?: true; channel: Api.TypeInputChannel; - }; + } export class LoadAsyncGraph extends Request, Api.TypeStatsGraph> { - // flags: undefined; + // flags: Api.Type; token: string; x?: long; - }; + } export class GetMegagroupStats extends Request, stats.TypeMegagroupStats> { - // flags: undefined; + // flags: Api.Type; dark?: true; channel: Api.TypeInputChannel; - }; + } export class GetMessagePublicForwards extends Request, stats.TypeMessageStats> { - // flags: undefined; + // flags: Api.Type; dark?: true; channel: Api.TypeInputChannel; msgId: int; - }; + } export class GetStoryStats extends Request, stats.TypeStoryStats> { - // flags: undefined; + // flags: Api.Type; dark?: true; peer: Api.TypeInputPeer; id: int; - }; + } export class GetStoryPublicForwards extends Request, stats.TypeBroadcastRevenueStats> { - // flags: undefined; + // flags: Api.Type; dark?: true; peer: Api.TypeInputPeer; - }; + } export class GetBroadcastRevenueWithdrawalUrl extends Request, stats.TypeBroadcastRevenueWithdrawalUrl> { peer: Api.TypeInputPeer; password: Api.TypeInputCheckPasswordSRP; - }; + } export class GetBroadcastRevenueTransactions extends Request, Bool> { chatlist: Api.TypeInputChatlist; slug: string; - }; + } export class EditExportedInvite extends Request, Api.TypeExportedChatlistInvite> { - // flags: undefined; + // flags: Api.Type; chatlist: Api.TypeInputChatlist; slug: string; title?: string; peers?: Api.TypeInputPeer[]; - }; + } export class GetExportedInvites extends Request, chatlists.TypeExportedInvites> { chatlist: Api.TypeInputChatlist; - }; + } export class CheckChatlistInvite extends Request, chatlists.TypeChatlistInvite> { slug: string; - }; + } export class JoinChatlistInvite extends Request, Api.TypeUpdates> { slug: string; peers: Api.TypeInputPeer[]; - }; + } export class GetChatlistUpdates extends Request, chatlists.TypeChatlistUpdates> { chatlist: Api.TypeInputChatlist; - }; + } export class JoinChatlistUpdates extends Request, Api.TypeUpdates> { chatlist: Api.TypeInputChatlist; peers: Api.TypeInputPeer[]; - }; + } export class HideChatlistUpdates extends Request, Bool> { chatlist: Api.TypeInputChatlist; - }; + } export class GetLeaveChatlistSuggestions extends Request, Api.TypePeer[]> { chatlist: Api.TypeInputChatlist; - }; + } export class LeaveChatlist extends Request, Api.TypeUpdates> { chatlist: Api.TypeInputChatlist; peers: Api.TypeInputPeer[]; - }; + } } export namespace stories { @@ -19291,9 +21010,9 @@ namespace Api { peer: Api.TypeInputPeer; }>, Bool> { peer: Api.TypeInputPeer; - }; + } export class SendStory extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; pinned?: true; noforwards?: true; fwdModified?: true; @@ -19322,9 +21041,9 @@ namespace Api { period?: int; fwdFromId?: Api.TypeInputPeer; fwdFromStory?: int; - }; + } export class EditStory extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; peer: Api.TypeInputPeer; id: int; media?: Api.TypeInputMedia; @@ -19341,14 +21060,14 @@ namespace Api { caption?: string; entities?: Api.TypeMessageEntity[]; privacyRules?: Api.TypeInputPrivacyRule[]; - }; + } export class DeleteStories extends Request, int[]> { peer: Api.TypeInputPeer; id: int[]; - }; + } export class TogglePinned extends Request, stories.TypeAllStories> { - // flags: undefined; + // flags: Api.Type; next?: true; hidden?: true; state?: string; - }; + } export class GetPinnedStories extends Request, stories.TypeStories> { peer: Api.TypeInputPeer; id: int[]; - }; + } export class ToggleAllStoriesHidden extends Request, Bool> { hidden: Bool; - }; + } export class ReadStories extends Request, int[]> { peer: Api.TypeInputPeer; maxId: int; - }; + } export class IncrementStoryViews extends Request, Bool> { peer: Api.TypeInputPeer; id: int[]; - }; + } export class GetStoryViewsList extends Request, stories.TypeStoryViewsList> { - // flags: undefined; + // flags: Api.Type; justContacts?: true; reactionsFirst?: true; forwardsFirst?: true; @@ -19433,21 +21152,21 @@ namespace Api { id: int; offset: string; limit: int; - }; + } export class GetStoriesViews extends Request, stories.TypeStoryViews> { peer: Api.TypeInputPeer; id: int[]; - }; + } export class ExportStoryLink extends Request, Api.TypeExportedStoryLink> { peer: Api.TypeInputPeer; id: int; - }; + } export class Report extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; past?: true; future?: true; - }; + } export class SendReaction extends Request, Api.TypeUpdates> { - // flags: undefined; + // flags: Api.Type; addToRecent?: true; peer: Api.TypeInputPeer; storyId: int; reaction: Api.TypeReaction; - }; + } export class GetPeerStories extends Request, stories.TypePeerStories> { peer: Api.TypeInputPeer; - }; - export class GetAllReadPeerStories extends Request {}; + } + export class GetAllReadPeerStories extends Request {} export class GetPeerMaxIDs extends Request, int[]> { id: Api.TypeInputPeer[]; - }; - export class GetChatsToSend extends Request {}; + } + export class GetChatsToSend extends Request {} export class TogglePeerStoriesHidden extends Request, Bool> { peer: Api.TypeInputPeer; hidden: Bool; - }; + } export class GetStoryReactionsList extends Request, stories.TypeStoryReactionsList> { - // flags: undefined; + // flags: Api.Type; forwardsFirst?: true; peer: Api.TypeInputPeer; id: int; reaction?: Api.TypeReaction; offset?: string; limit: int; - }; + } export class TogglePinnedToTop extends Request, Bool> { peer: Api.TypeInputPeer; id: int[]; - }; + } export class SearchPosts extends Request, stories.TypeFoundStories> { - // flags: undefined; + // flags: Api.Type; hashtag?: string; area?: Api.TypeMediaArea; peer?: Api.TypeInputPeer; offset: string; limit: int; - }; + } } export namespace premium { export class GetBoostsList extends Request, premium.TypeBoostsList> { - // flags: undefined; + // flags: Api.Type; gifts?: true; peer: Api.TypeInputPeer; offset: string; limit: int; - }; - export class GetMyBoosts extends Request {}; + } + export class GetMyBoosts extends Request {} export class ApplyBoost extends Request, premium.TypeMyBoosts> { - // flags: undefined; + // flags: Api.Type; slots?: int[]; peer: Api.TypeInputPeer; - }; + } export class GetBoostsStatus extends Request, premium.TypeBoostsStatus> { peer: Api.TypeInputPeer; - }; + } export class GetUserBoosts extends Request, premium.TypeBoostsList> { peer: Api.TypeInputPeer; userId: Api.TypeInputUser; - }; + } } export namespace smsjobs { - export class IsEligibleToJoin extends Request {}; - export class Join extends Request {}; - export class Leave extends Request {}; + export class IsEligibleToJoin extends Request {} + export class Join extends Request {} + export class Leave extends Request {} export class UpdateSettings extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; allowInternational?: true; - }; - export class GetStatus extends Request {}; + } + export class GetStatus extends Request {} export class GetSmsJob extends Request, Api.TypeSmsJob> { jobId: string; - }; + } export class FinishJob extends Request, Bool> { - // flags: undefined; + // flags: Api.Type; jobId: string; error?: string; - }; + } } export namespace fragment { @@ -19612,7 +21331,7 @@ namespace Api { collectible: Api.TypeInputCollectible; }>, fragment.TypeCollectibleInfo> { collectible: Api.TypeInputCollectible; - }; + } } export type AnyRequest = InvokeAfterMsg | InvokeAfterMsgs | InitConnection | InvokeWithLayer | InvokeWithoutUpdates | InvokeWithMessagesRange | InvokeWithTakeout | InvokeWithBusinessConnection | InvokeWithGooglePlayIntegrity | InvokeWithApnsSecret | ReqPq | ReqPqMulti | ReqPqMultiNew | ReqDHParams | SetClientDHParams | DestroyAuthKey | RpcDropAnswer | GetFutureSalts | Ping | PingDelayDisconnect | DestroySession diff --git a/src/lib/gramjs/tl/api.js b/src/lib/gramjs/tl/api.js index 0db30cbb6..09e3c86fd 100644 --- a/src/lib/gramjs/tl/api.js +++ b/src/lib/gramjs/tl/api.js @@ -1,406 +1,5 @@ -const { - parseTl, - serializeBytes, - serializeDate, -} = require('./generationHelpers'); -const { - toSignedLittleBuffer, -} = require('../Helpers'); +import { buildApiFromTlSchema } from './apiHelpers'; -const tlContent = require('./apiTl'); -const schemeContent = require('./schemaTl'); +const Api = buildApiFromTlSchema(); -/* CONTEST -const NAMED_AUTO_CASTS = new Set([ - 'chatId,int' -]) -const NAMED_BLACKLIST = new Set([ - 'discardEncryption' -]) -const AUTO_CASTS = new Set([ - 'InputPeer', - 'InputChannel', - 'InputUser', - 'InputDialogPeer', - 'InputNotifyPeer', - 'InputMedia', - 'InputPhoto', - 'InputMessage', - 'InputDocument', - 'InputChatPhoto' -]) - - */ -// eslint-disable-next-line no-restricted-globals -const CACHING_SUPPORTED = typeof self !== 'undefined' && self.localStorage !== undefined; - -const CACHE_KEY = 'GramJs:apiCache'; - -function buildApiFromTlSchema() { - let definitions; - const fromCache = CACHING_SUPPORTED && loadFromCache(); - - if (fromCache) { - definitions = fromCache; - } else { - definitions = loadFromTlSchemas(); - - if (CACHING_SUPPORTED) { - localStorage.setItem(CACHE_KEY, JSON.stringify(definitions)); - } - } - - return mergeWithNamespaces( - createClasses('constructor', definitions.constructors), - createClasses('request', definitions.requests), - ); -} - -function loadFromCache() { - const jsonCache = localStorage.getItem(CACHE_KEY); - return jsonCache && JSON.parse(jsonCache); -} - -function loadFromTlSchemas() { - const [constructorParamsApi, functionParamsApi] = extractParams(tlContent); - const [constructorParamsSchema, functionParamsSchema] = extractParams(schemeContent); - const constructors = [].concat(constructorParamsApi, constructorParamsSchema); - const requests = [].concat(functionParamsApi, functionParamsSchema); - - return { - constructors, - requests, - }; -} - -function mergeWithNamespaces(obj1, obj2) { - const result = { ...obj1 }; - - Object.keys(obj2) - .forEach((key) => { - if (typeof obj2[key] === 'function' || !result[key]) { - result[key] = obj2[key]; - } else { - Object.assign(result[key], obj2[key]); - } - }); - - return result; -} - -function extractParams(fileContent) { - const f = parseTl(fileContent); - const constructors = []; - const functions = []; - for (const d of f) { - if (d.isFunction) { - functions.push(d); - } else { - constructors.push(d); - } - } - return [constructors, functions]; -} - -function argToBytes(x, type) { - switch (type) { - case 'int': { - const i = Buffer.alloc(4); - i.writeInt32LE(x, 0); - return i; - } - case 'long': - return toSignedLittleBuffer(x, 8); - case 'int128': - return toSignedLittleBuffer(x, 16); - case 'int256': - return toSignedLittleBuffer(x, 32); - case 'double': { - const d = Buffer.alloc(8); - d.writeDoubleLE(x, 0); - return d; - } - case 'string': - return serializeBytes(x); - case 'Bool': - return x ? Buffer.from('b5757299', 'hex') : Buffer.from('379779bc', 'hex'); - case 'true': - return Buffer.alloc(0); - case 'bytes': - return serializeBytes(x); - case 'date': - return serializeDate(x); - default: - return x.getBytes(); - } -} - -/* -CONTEST -async function getInputFromResolve(utils, client, peer, peerType) { - switch (peerType) { - case 'InputPeer': - return utils.getInputPeer(await client.getInputEntity(peer)) - case 'InputChannel': - return utils.getInputChannel(await client.getInputEntity(peer)) - case 'InputUser': - return utils.getInputUser(await client.getInputEntity(peer)) - case 'InputDialogPeer': - return await client._getInputDialog(peer) - case 'InputNotifyPeer': - return await client._getInputNotify(peer) - case 'InputMedia': - return utils.getInputMedia(peer) - case 'InputPhoto': - return utils.getInputPhoto(peer) - case 'InputMessage': - return utils.getInputMessage(peer) - case 'InputDocument': - return utils.getInputDocument(peer) - case 'InputChatPhoto': - return utils.getInputChatPhoto(peer) - case 'chatId,int' : - return await client.getPeerId(peer, false) - default: - throw new Error('unsupported peer type : ' + peerType) - } -} -*/ -function getArgFromReader(reader, arg) { - if (arg.isVector) { - if (arg.useVectorId) { - reader.readInt(); - } - const temp = []; - const len = reader.readInt(); - arg.isVector = false; - for (let i = 0; i < len; i++) { - temp.push(getArgFromReader(reader, arg)); - } - arg.isVector = true; - return temp; - } else if (arg.flagIndicator) { - return reader.readInt(); - } else { - switch (arg.type) { - case 'int': - return reader.readInt(); - case 'long': - return reader.readLong(); - case 'int128': - return reader.readLargeInt(128); - case 'int256': - return reader.readLargeInt(256); - case 'double': - return reader.readDouble(); - case 'string': - return reader.tgReadString(); - case 'Bool': - return reader.tgReadBool(); - case 'true': - return true; - case 'bytes': - return reader.tgReadBytes(); - case 'date': - return reader.tgReadDate(); - default: - if (!arg.skipConstructorId) { - return reader.tgReadObject(); - } else { - throw new Error(`Unknown type ${arg}`); - } - } - } -} - -function createClasses(classesType, params) { - const classes = {}; - for (const classParams of params) { - const { - name, - constructorId, - subclassOfId, - argsConfig, - namespace, - result, - } = classParams; - const fullName = [namespace, name].join('.') - .replace(/^\./, ''); - - class VirtualClass { - static CONSTRUCTOR_ID = constructorId; - - static SUBCLASS_OF_ID = subclassOfId; - - static className = fullName; - - static classType = classesType; - - CONSTRUCTOR_ID = constructorId; - - SUBCLASS_OF_ID = subclassOfId; - - className = fullName; - - classType = classesType; - - constructor(args) { - args = args || {}; - Object.keys(args) - .forEach((argName) => { - this[argName] = args[argName]; - }); - } - - static fromReader(reader) { - const args = {}; - - for (const argName in argsConfig) { - if (argsConfig.hasOwnProperty(argName)) { - const arg = argsConfig[argName]; - if (arg.isFlag) { - const flagGroupSuffix = arg.flagGroup > 1 ? arg.flagGroup : ''; - const flagValue = args[`flags${flagGroupSuffix}`] & (1 << arg.flagIndex); - if (arg.type === 'true') { - args[argName] = Boolean(flagValue); - continue; - } - - args[argName] = flagValue ? getArgFromReader(reader, arg) : undefined; - } else { - args[argName] = getArgFromReader(reader, arg); - } - } - } - return new VirtualClass(args); - } - - getBytes() { - // The next is pseudo-code: - const idForBytes = this.CONSTRUCTOR_ID; - const c = Buffer.alloc(4); - c.writeUInt32LE(idForBytes, 0); - const buffers = [c]; - for (const arg in argsConfig) { - if (argsConfig.hasOwnProperty(arg)) { - if (argsConfig[arg].isFlag) { - if ((this[arg] === false && argsConfig[arg].type === 'true') - || this[arg] === undefined) { - continue; - } - } - if (argsConfig[arg].isVector) { - if (argsConfig[arg].useVectorId) { - buffers.push(Buffer.from('15c4b51c', 'hex')); - } - const l = Buffer.alloc(4); - l.writeInt32LE(this[arg].length, 0); - buffers.push(l, Buffer.concat(this[arg].map((x) => argToBytes(x, argsConfig[arg].type)))); - } else if (argsConfig[arg].flagIndicator) { - if (!Object.values(argsConfig) - .some((f) => f.isFlag)) { - buffers.push(Buffer.alloc(4)); - } else { - let flagCalculate = 0; - for (const f in argsConfig) { - if (argsConfig[f].isFlag) { - if ((this[f] === false && argsConfig[f].type === 'true') - || this[f] === undefined) { - flagCalculate |= 0; - } else { - flagCalculate |= 1 << argsConfig[f].flagIndex; - } - } - } - const f = Buffer.alloc(4); - f.writeUInt32LE(flagCalculate, 0); - buffers.push(f); - } - } else { - buffers.push(argToBytes(this[arg], argsConfig[arg].type)); - - if (this[arg] && typeof this[arg].getBytes === 'function') { - let boxed = (argsConfig[arg].type.charAt(argsConfig[arg].type.indexOf('.') + 1)); - boxed = boxed === boxed.toUpperCase(); - if (!boxed) { - buffers.shift(); - } - } - } - } - } - return Buffer.concat(buffers); - } - - readResult(reader) { - if (classesType !== 'request') { - throw new Error('`readResult()` called for non-request instance'); - } - - const m = result.match(/Vector<(int|long)>/); - if (m) { - reader.readInt(); - const temp = []; - const len = reader.readInt(); - if (m[1] === 'int') { - for (let i = 0; i < len; i++) { - temp.push(reader.readInt()); - } - } else { - for (let i = 0; i < len; i++) { - temp.push(reader.readLong()); - } - } - return temp; - } else { - return reader.tgReadObject(); - } - } - - /* CONTEST - async resolve(client, utils) { - - if (classesType !== 'request') { - throw new Error('`resolve()` called for non-request instance') - } - - for (const arg in argsConfig) { - if (argsConfig.hasOwnProperty(arg)) { - if (!AUTO_CASTS.has(argsConfig[arg].type)) { - if (!NAMED_AUTO_CASTS.has(`${argsConfig[arg].name},${argsConfig[arg].type}`)) { - continue - } - } - if (argsConfig[arg].isFlag) { - if (!this[arg]) { - continue - } - } - if (argsConfig[arg].isVector) { - const temp = [] - for (const x of this[arg]) { - temp.push(await getInputFromResolve(utils, client, x, argsConfig[arg].type)) - } - this[arg] = temp - } else { - this[arg] = await getInputFromResolve(utils, client, this[arg], argsConfig[arg].type) - } - } - } - } */ - } - - if (namespace) { - if (!classes[namespace]) { - classes[namespace] = {}; - } - classes[namespace][name] = VirtualClass; - } else { - classes[name] = VirtualClass; - } - } - - return classes; -} - -module.exports = buildApiFromTlSchema(); +export default Api; diff --git a/src/lib/gramjs/tl/apiHelpers.ts b/src/lib/gramjs/tl/apiHelpers.ts new file mode 100644 index 000000000..ec274a365 --- /dev/null +++ b/src/lib/gramjs/tl/apiHelpers.ts @@ -0,0 +1,323 @@ +import type { BinaryReader } from '../extensions'; + +import tlContent from './apiTl'; +import { + type GenerationArgConfig, type GenerationEntryConfig, parseTl, serializeBytes, serializeDate, +} from './generationHelpers'; +import schemeContent from './schemaTl'; + +import { toSignedLittleBuffer } from '../Helpers'; + +// eslint-disable-next-line no-restricted-globals +const CACHING_SUPPORTED = typeof self !== 'undefined' && self.localStorage !== undefined; + +const CACHE_KEY = 'GramJs:apiCache'; + +type UnsaveVirtualClass = Record; + +export function buildApiFromTlSchema() { + let definitions; + const fromCache = CACHING_SUPPORTED && loadFromCache(); + + if (fromCache) { + definitions = fromCache; + } else { + definitions = loadFromTlSchemas(); + + if (CACHING_SUPPORTED) { + localStorage.setItem(CACHE_KEY, JSON.stringify(definitions)); + } + } + + return mergeWithNamespaces( + createClasses('constructor', definitions.constructors), + createClasses('request', definitions.requests), + ); +} + +function loadFromCache(): { constructors: GenerationEntryConfig[]; requests: GenerationEntryConfig[] } { + const jsonCache = localStorage.getItem(CACHE_KEY); + return jsonCache && JSON.parse(jsonCache); +} + +function loadFromTlSchemas() { + const [constructorParamsApi, functionParamsApi] = extractParams(tlContent); + const [constructorParamsSchema, functionParamsSchema] = extractParams(schemeContent); + const constructors = ([] as GenerationEntryConfig[]).concat(constructorParamsApi, constructorParamsSchema); + const requests = ([] as GenerationEntryConfig[]).concat(functionParamsApi, functionParamsSchema); + + return { + constructors, + requests, + }; +} + +function mergeWithNamespaces(obj1: Record, obj2: Record): Record { + const result: Record = { ...obj1 }; + + Object.keys(obj2) + .forEach((key) => { + if (typeof obj2[key] === 'function' || !result[key]) { + result[key] = obj2[key]; + } else { + Object.assign(result[key], obj2[key]); + } + }); + + return result; +} + +function extractParams(fileContent: string) { + const f = parseTl(fileContent); + const constructors = []; + const functions = []; + for (const d of f) { + if (d.isFunction) { + functions.push(d); + } else { + constructors.push(d); + } + } + return [constructors, functions]; +} + +function argToBytes(x: any, type: string) { + switch (type) { + case 'int': { + const i = Buffer.alloc(4); + i.writeInt32LE(x, 0); + return i; + } + case 'long': + return toSignedLittleBuffer(x, 8); + case 'int128': + return toSignedLittleBuffer(x, 16); + case 'int256': + return toSignedLittleBuffer(x, 32); + case 'double': { + const d = Buffer.alloc(8); + d.writeDoubleLE(x, 0); + return d; + } + case 'string': + return serializeBytes(x); + case 'Bool': + return x ? Buffer.from('b5757299', 'hex') : Buffer.from('379779bc', 'hex'); + case 'true': + return Buffer.alloc(0); + case 'bytes': + return serializeBytes(x); + case 'date': + return serializeDate(x); + default: + return x.getBytes(); + } +} + +function getArgFromReader(reader: BinaryReader, arg: GenerationArgConfig): any { + if (arg.isVector) { + if (arg.useVectorId) { + reader.readInt(); + } + const temp = []; + const len = reader.readInt(); + arg.isVector = false; + for (let i = 0; i < len; i++) { + temp.push(getArgFromReader(reader, arg)); + } + arg.isVector = true; + return temp; + } else if (arg.flagIndicator) { + return reader.readInt(); + } else { + switch (arg.type) { + case 'int': + return reader.readInt(); + case 'long': + return reader.readLong(); + case 'int128': + return reader.readLargeInt(128); + case 'int256': + return reader.readLargeInt(256); + case 'double': + return reader.readDouble(); + case 'string': + return reader.tgReadString(); + case 'Bool': + return reader.tgReadBool(); + case 'true': + return true; + case 'bytes': + return reader.tgReadBytes(); + case 'date': + return reader.tgReadDate(); + default: + if (!arg.skipConstructorId) { + return reader.tgReadObject(); + } else { + throw new Error(`Unknown type ${arg}`); + } + } + } +} + +function createClasses(classesType: 'constructor' | 'request', params: GenerationEntryConfig[]) { + const classes: Record = {}; + for (const classParams of params) { + const { + name, + constructorId, + subclassOfId, + argsConfig, + namespace, + result, + } = classParams; + const fullName = [namespace, name].join('.') + .replace(/^\./, ''); + + class VirtualClass { + static CONSTRUCTOR_ID = constructorId; + + static SUBCLASS_OF_ID = subclassOfId; + + static className = fullName; + + static classType = classesType; + + CONSTRUCTOR_ID = constructorId; + + SUBCLASS_OF_ID = subclassOfId; + + className = fullName; + + classType = classesType; + + constructor(args: Record) { + args = args || {}; + Object.keys(args) + .forEach((argName) => { + (this as UnsaveVirtualClass)[argName] = args[argName]; + }); + } + + static fromReader(reader: BinaryReader) { + const args: Record = {}; + + for (const argName in argsConfig) { + if (argsConfig.hasOwnProperty(argName)) { + const arg = argsConfig[argName]; + if (arg.isFlag) { + const flagGroupSuffix = arg.flagGroup > 1 ? arg.flagGroup : ''; + const flagValue = args[`flags${flagGroupSuffix}`] & (1 << arg.flagIndex); + if (arg.type === 'true') { + args[argName] = Boolean(flagValue); + continue; + } + + args[argName] = flagValue ? getArgFromReader(reader, arg) : undefined; + } else { + args[argName] = getArgFromReader(reader, arg); + } + } + } + return new VirtualClass(args); + } + + getBytes() { + // The next is pseudo-code: + const idForBytes = this.CONSTRUCTOR_ID; + const c = Buffer.alloc(4); + c.writeUInt32LE(idForBytes, 0); + const buffers = [c]; + for (const arg in argsConfig) { + if (argsConfig.hasOwnProperty(arg)) { + if (argsConfig[arg].isFlag) { + if (((this as UnsaveVirtualClass)[arg] === false && argsConfig[arg].type === 'true') + || (this as UnsaveVirtualClass)[arg] === undefined) { + continue; + } + } + if (argsConfig[arg].isVector) { + if (argsConfig[arg].useVectorId) { + buffers.push(Buffer.from('15c4b51c', 'hex')); + } + const l = Buffer.alloc(4); + l.writeInt32LE((this as UnsaveVirtualClass)[arg].length, 0); + buffers.push(l, Buffer.concat((this as UnsaveVirtualClass)[arg].map((x: any) => ( + argToBytes(x, argsConfig[arg].type) + )))); + } else if (argsConfig[arg].flagIndicator) { + if (!Object.values(argsConfig) + .some((f) => f.isFlag)) { + buffers.push(Buffer.alloc(4)); + } else { + let flagCalculate = 0; + for (const f in argsConfig) { + if (argsConfig[f].isFlag) { + if (((this as UnsaveVirtualClass)[f] === false && argsConfig[f].type === 'true') + || (this as UnsaveVirtualClass)[f] === undefined) { + flagCalculate |= 0; + } else { + flagCalculate |= 1 << argsConfig[f].flagIndex; + } + } + } + const f = Buffer.alloc(4); + f.writeUInt32LE(flagCalculate, 0); + buffers.push(f); + } + } else { + buffers.push(argToBytes((this as UnsaveVirtualClass)[arg], argsConfig[arg].type)); + + if ((this as UnsaveVirtualClass)[arg] + && typeof (this as UnsaveVirtualClass)[arg].getBytes === 'function') { + const firstChar = (argsConfig[arg].type.charAt(argsConfig[arg].type.indexOf('.') + 1)); + const boxed = firstChar === firstChar.toUpperCase(); + if (!boxed) { + buffers.shift(); + } + } + } + } + } + return Buffer.concat(buffers); + } + + readResult(reader: BinaryReader) { + if (classesType !== 'request') { + throw new Error('`readResult()` called for non-request instance'); + } + + const m = result.match(/Vector<(int|long)>/); + if (m) { + reader.readInt(); + const temp = []; + const len = reader.readInt(); + if (m[1] === 'int') { + for (let i = 0; i < len; i++) { + temp.push(reader.readInt()); + } + } else { + for (let i = 0; i < len; i++) { + temp.push(reader.readLong()); + } + } + return temp; + } else { + return reader.tgReadObject(); + } + } + } + + if (namespace) { + if (!classes[namespace]) { + classes[namespace] = {}; + } + classes[namespace][name] = VirtualClass; + } else { + classes[name] = VirtualClass; + } + } + + return classes; +} diff --git a/src/lib/gramjs/tl/apiTl.js b/src/lib/gramjs/tl/apiTl.ts similarity index 99% rename from src/lib/gramjs/tl/apiTl.js rename to src/lib/gramjs/tl/apiTl.ts index d20f52491..74d43deb3 100644 --- a/src/lib/gramjs/tl/apiTl.js +++ b/src/lib/gramjs/tl/apiTl.ts @@ -1,4 +1,4 @@ -module.exports = `boolFalse#bc799737 = Bool; +export default `boolFalse#bc799737 = Bool; boolTrue#997275b5 = Bool; true#3fedd339 = True; vector#1cb5c415 {t:Type} # [ t ] = Vector t; diff --git a/src/lib/gramjs/tl/core/GZIPPacked.js b/src/lib/gramjs/tl/core/GZIPPacked.ts similarity index 60% rename from src/lib/gramjs/tl/core/GZIPPacked.js rename to src/lib/gramjs/tl/core/GZIPPacked.ts index 204f881d4..d9b657a60 100644 --- a/src/lib/gramjs/tl/core/GZIPPacked.js +++ b/src/lib/gramjs/tl/core/GZIPPacked.ts @@ -1,22 +1,29 @@ -const { inflate } = require('pako/dist/pako_inflate'); -const { serializeBytes } = require('../index'); +import { inflate } from 'pako/dist/pako_inflate'; -// CONTEST const { deflate } = require('pako/dist/pako_deflate') +import type { BinaryReader } from '../../extensions'; -class GZIPPacked { +import { serializeBytes } from '..'; + +export default class GZIPPacked { static CONSTRUCTOR_ID = 0x3072cfa1; static classType = 'constructor'; - constructor(data) { + data: Buffer; + + private CONSTRUCTOR_ID: number; + + private classType: string; + + constructor(data: Buffer) { this.data = data; this.CONSTRUCTOR_ID = 0x3072cfa1; this.classType = 'constructor'; } - static async gzipIfSmaller(contentRelated, data) { + static async gzipIfSmaller(contentRelated: boolean, data: Buffer) { if (contentRelated && data.length > 512) { - const gzipped = await (new GZIPPacked(data)).toBytes(); + const gzipped = await new GZIPPacked(data).toBytes(); if (gzipped.length < data.length) { return gzipped; } @@ -24,28 +31,16 @@ class GZIPPacked { return data; } - static gzip(input) { + static gzip(input: Buffer) { return Buffer.from(input); // TODO this usually makes it faster for large requests // return Buffer.from(deflate(input, { level: 9, gzip: true })) } - static ungzip(input) { + static ungzip(input: Buffer) { return Buffer.from(inflate(input)); } - static read(reader) { - const constructor = reader.readInt(false); - if (constructor !== GZIPPacked.CONSTRUCTOR_ID) { - throw new Error('not equal'); - } - return GZIPPacked.gzip(reader.tgReadBytes()); - } - - static async fromReader(reader) { - return new GZIPPacked(await GZIPPacked.ungzip(reader.tgReadBytes())); - } - async toBytes() { const g = Buffer.alloc(4); g.writeUInt32LE(GZIPPacked.CONSTRUCTOR_ID, 0); @@ -54,6 +49,17 @@ class GZIPPacked { serializeBytes(await GZIPPacked.gzip(this.data)), ]); } -} -module.exports = GZIPPacked; + static read(reader: BinaryReader) { + const constructor = reader.readInt(false); + if (constructor !== GZIPPacked.CONSTRUCTOR_ID) { + throw new Error('not equal'); + } + return GZIPPacked.gzip(reader.tgReadBytes()); + } + + static async fromReader(reader: BinaryReader) { + const data = reader.tgReadBytes(); + return new GZIPPacked(await GZIPPacked.ungzip(data)); + } +} diff --git a/src/lib/gramjs/tl/core/MessageContainer.js b/src/lib/gramjs/tl/core/MessageContainer.ts similarity index 72% rename from src/lib/gramjs/tl/core/MessageContainer.js rename to src/lib/gramjs/tl/core/MessageContainer.ts index 879003449..3ba6233a2 100644 --- a/src/lib/gramjs/tl/core/MessageContainer.js +++ b/src/lib/gramjs/tl/core/MessageContainer.ts @@ -1,6 +1,8 @@ -const TLMessage = require('./TLMessage'); +import type { BinaryReader } from '../../extensions'; -class MessageContainer { +import TLMessage from './TLMessage'; + +export default class MessageContainer { static CONSTRUCTOR_ID = 0x73f1f8dc; static classType = 'constructor'; @@ -20,27 +22,31 @@ class MessageContainer { // other factors like size per request, but we cannot know this. static MAXIMUM_LENGTH = 100; - constructor(messages) { + private CONSTRUCTOR_ID: number; + + private messages: any[]; + + private classType: string; + + constructor(messages: any[]) { this.CONSTRUCTOR_ID = 0x73f1f8dc; this.messages = messages; this.classType = 'constructor'; } - static fromReader(reader) { + static fromReader(reader: BinaryReader) { const messages = []; - const length = reader.readInt(); - for (let x = 0; x < length; x++) { + const totalLength = reader.readInt(); + for (let x = 0; x < totalLength; x++) { const msgId = reader.readLong(); const seqNo = reader.readInt(); - const containerLength = reader.readInt(); + const length = reader.readInt(); const before = reader.tellPosition(); const obj = reader.tgReadObject(); - reader.setPosition(before + containerLength); + reader.setPosition(before + length); const tlMessage = new TLMessage(msgId, seqNo, obj); messages.push(tlMessage); } return new MessageContainer(messages); } } - -module.exports = MessageContainer; diff --git a/src/lib/gramjs/tl/core/RPCResult.js b/src/lib/gramjs/tl/core/RPCResult.js deleted file mode 100644 index 8c4ef9590..000000000 --- a/src/lib/gramjs/tl/core/RPCResult.js +++ /dev/null @@ -1,34 +0,0 @@ -const { RpcError } = require('../index').constructors; -const GZIPPacked = require('./GZIPPacked'); - -class RPCResult { - static CONSTRUCTOR_ID = 0xf35c6d01; - - static classType = 'constructor'; - - constructor(reqMsgId, body, error) { - this.CONSTRUCTOR_ID = 0xf35c6d01; - this.reqMsgId = reqMsgId; - this.body = body; - this.error = error; - this.classType = 'constructor'; - } - - static async fromReader(reader) { - const msgId = reader.readLong(); - const innerCode = reader.readInt(false); - if (innerCode === RpcError.CONSTRUCTOR_ID) { - return new RPCResult(msgId, undefined, RpcError.fromReader(reader)); - } - if (innerCode === GZIPPacked.CONSTRUCTOR_ID) { - return new RPCResult(msgId, (await GZIPPacked.fromReader(reader)).data); - } - reader.seek(-4); - // This reader.read() will read more than necessary, but it's okay. - // We could make use of MessageContainer's length here, but since - // it's not necessary we don't need to care about it. - return new RPCResult(msgId, reader.read(), undefined); - } -} - -module.exports = RPCResult; diff --git a/src/lib/gramjs/tl/core/RPCResult.ts b/src/lib/gramjs/tl/core/RPCResult.ts new file mode 100644 index 000000000..f3afa12f8 --- /dev/null +++ b/src/lib/gramjs/tl/core/RPCResult.ts @@ -0,0 +1,58 @@ +import type BigInt from 'big-integer'; + +import type { BinaryReader } from '../../extensions'; + +import Api from '../api'; + +import GZIPPacked from './GZIPPacked'; + +export default class RPCResult { + static CONSTRUCTOR_ID = 0xf35c6d01; + + static classType = 'constructor'; + + private CONSTRUCTOR_ID: number; + + private reqMsgId: BigInt.BigInteger; + + private body?: Buffer; + + private error?: Api.RpcError; + + private classType: string; + + constructor( + reqMsgId: BigInt.BigInteger, + body?: Buffer, + error?: Api.RpcError, + ) { + this.CONSTRUCTOR_ID = 0xf35c6d01; + this.reqMsgId = reqMsgId; + this.body = body; + this.error = error; + this.classType = 'constructor'; + } + + static async fromReader(reader: BinaryReader) { + const msgId = reader.readLong(); + const innerCode = reader.readInt(false); + if (innerCode === Api.RpcError.CONSTRUCTOR_ID) { + return new RPCResult( + msgId, + undefined, + Api.RpcError.fromReader(reader), + ); + } + if (innerCode === GZIPPacked.CONSTRUCTOR_ID) { + return new RPCResult( + msgId, + (await GZIPPacked.fromReader(reader)).data, + ); + } + reader.seek(-4); + // This reader.read() will read more than necessary, but it's okay. + // We could make use of MessageContainer's length here, but since + // it's not necessary we don't need to care about it. + return new RPCResult(msgId, reader.read(), undefined); + } +} diff --git a/src/lib/gramjs/tl/core/TLMessage.js b/src/lib/gramjs/tl/core/TLMessage.js deleted file mode 100644 index b15ce08a6..000000000 --- a/src/lib/gramjs/tl/core/TLMessage.js +++ /dev/null @@ -1,14 +0,0 @@ -class TLMessage { - static SIZE_OVERHEAD = 12; - - static classType = 'constructor'; - - constructor(msgId, seqNo, obj) { - this.msgId = msgId; - this.seqNo = seqNo; - this.obj = obj; - this.classType = 'constructor'; - } -} - -module.exports = TLMessage; diff --git a/src/lib/gramjs/tl/core/TLMessage.ts b/src/lib/gramjs/tl/core/TLMessage.ts new file mode 100644 index 000000000..6ae90afae --- /dev/null +++ b/src/lib/gramjs/tl/core/TLMessage.ts @@ -0,0 +1,19 @@ +import type BigInt from 'big-integer'; + +export default class TLMessage { + static SIZE_OVERHEAD = 12; + + static classType = 'constructor'; + + msgId: BigInt.BigInteger; + + private seqNo: number; + + obj: any; + + constructor(msgId: bigInt.BigInteger, seqNo: number, obj: any) { + this.msgId = msgId; + this.seqNo = seqNo; + this.obj = obj; + } +} diff --git a/src/lib/gramjs/tl/core/index.js b/src/lib/gramjs/tl/core/index.js deleted file mode 100644 index 9dc8c8335..000000000 --- a/src/lib/gramjs/tl/core/index.js +++ /dev/null @@ -1,18 +0,0 @@ -const TLMessage = require('./TLMessage'); -const RPCResult = require('./RPCResult'); -const MessageContainer = require('./MessageContainer'); -const GZIPPacked = require('./GZIPPacked'); - -const coreObjects = { - [RPCResult.CONSTRUCTOR_ID]: RPCResult, - [GZIPPacked.CONSTRUCTOR_ID]: GZIPPacked, - [MessageContainer.CONSTRUCTOR_ID]: MessageContainer, -}; - -module.exports = { - TLMessage, - RPCResult, - MessageContainer, - GZIPPacked, - coreObjects, -}; diff --git a/src/lib/gramjs/tl/core/index.ts b/src/lib/gramjs/tl/core/index.ts new file mode 100644 index 000000000..5dddd839b --- /dev/null +++ b/src/lib/gramjs/tl/core/index.ts @@ -0,0 +1,16 @@ +import GZIPPacked from './GZIPPacked'; +import MessageContainer from './MessageContainer'; +import RPCResult from './RPCResult'; +import TLMessage from './TLMessage'; + +export const coreObjects = new Map([ + [RPCResult.CONSTRUCTOR_ID, RPCResult], + [GZIPPacked.CONSTRUCTOR_ID, GZIPPacked], + [MessageContainer.CONSTRUCTOR_ID, MessageContainer], +]); +export { + RPCResult, + TLMessage, + MessageContainer, + GZIPPacked, +}; diff --git a/src/lib/gramjs/tl/generateModules.js b/src/lib/gramjs/tl/generateModules.ts similarity index 70% rename from src/lib/gramjs/tl/generateModules.js rename to src/lib/gramjs/tl/generateModules.ts index f2dfa6728..35dfda136 100644 --- a/src/lib/gramjs/tl/generateModules.js +++ b/src/lib/gramjs/tl/generateModules.ts @@ -1,9 +1,9 @@ -const fs = require('fs'); -const path = require('path'); +import fs from 'fs'; +import path from 'path'; -require('./types-generator/generate'); +import './types-generator/generate'; -function generateSchema(input, output, reducedMethods) { +function generateSchema(input: string, output: string, reducedMethods?: string) { let apiTl = fs.readFileSync( path.resolve(__dirname, input), 'utf-8', @@ -11,12 +11,12 @@ function generateSchema(input, output, reducedMethods) { if (reducedMethods) { apiTl = stripTl(apiTl); - const methodList = JSON.parse(fs.readFileSync( + const methodList: string[] = JSON.parse(fs.readFileSync( path.resolve(__dirname, reducedMethods), 'utf-8', )); let isFunction = false; - const reducedApiTl = []; + const reducedApiTl: string[] = []; for (const line of apiTl.split('\n')) { if (!line) { @@ -34,7 +34,7 @@ function generateSchema(input, output, reducedMethods) { if (!isFunction) { reducedApiTl.push(line); - } else if (methodList.includes(line.match(/([\w.]+)#/)[1])) { + } else if (methodList.includes(line.match(/([\w.]+)#/)![1])) { reducedApiTl.push(line); } } @@ -43,7 +43,7 @@ function generateSchema(input, output, reducedMethods) { fs.writeFileSync( path.resolve(__dirname, output), - `module.exports = \`${stripTl(apiTl)}\`;`, + `export default \`${stripTl(apiTl)}\`;`, ); } @@ -51,11 +51,11 @@ function main() { const args = process.argv.slice(2); const FULL_SCHEMA = args.length && args[0] === 'full'; - generateSchema('./static/api.tl', './apiTl.js', !FULL_SCHEMA && './static/api.json'); - generateSchema('./static/schema.tl', './schemaTl.js', !FULL_SCHEMA && './static/schema.json'); + generateSchema('./static/api.tl', './apiTl.ts', !FULL_SCHEMA ? './static/api.json' : undefined); + generateSchema('./static/schema.tl', './schemaTl.ts', !FULL_SCHEMA ? './static/schema.json' : undefined); } -function stripTl(tl) { +function stripTl(tl: string) { return tl.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '') // Remove comments .replace(/\n\s*\n/g, '\n') // Trim & add newline .replace(/`/g, '\\`') // Escape backticks diff --git a/src/lib/gramjs/tl/generationHelpers.js b/src/lib/gramjs/tl/generationHelpers.ts similarity index 85% rename from src/lib/gramjs/tl/generationHelpers.js rename to src/lib/gramjs/tl/generationHelpers.ts index 5e72ed99b..55cd6ca47 100644 --- a/src/lib/gramjs/tl/generationHelpers.js +++ b/src/lib/gramjs/tl/generationHelpers.ts @@ -1,8 +1,31 @@ -const snakeToCamelCase = (name) => { +import { crc32 } from '../Helpers'; + +export interface GenerationEntryConfig { + name: string; + constructorId: number; + argsConfig: Record; + subclassOfId: number; + result: string; + isFunction?: boolean; + namespace: string | undefined; +} + +export interface GenerationArgConfig { + isVector: boolean; + isFlag: boolean; + skipConstructorId: boolean; + flagGroup: number; + flagIndex: number; + flagIndicator: boolean; + type: string; + useVectorId: boolean | undefined; +} + +const snakeToCamelCase = (name: string) => { const result = name.replace(/(?:^|_)([a-z])/g, (_, g) => g.toUpperCase()); return result.replace(/_/g, ''); }; -const variableSnakeToCamelCase = (str) => str.replace( +const variableSnakeToCamelCase = (str: string) => str.replace( /([-_][a-z])/g, (group) => group.toUpperCase() .replace('-', '') @@ -30,39 +53,7 @@ const AUTH_KEY_TYPES = new Set([ 0x3072cfa1, // gzip_packed ]); -// This is copy-pasted from `gramjs/Helpers.js` to not depend on TypeScript modules -function makeCRCTable() { - let c; - const crcTable = []; - for (let n = 0; n < 256; n++) { - c = n; - for (let k = 0; k < 8; k++) { - c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); - } - crcTable[n] = c; - } - return crcTable; -} - -let crcTable; - -function crc32(buf) { - if (!crcTable) { - crcTable = makeCRCTable(); - } - if (!Buffer.isBuffer(buf)) { - buf = Buffer.from(buf); - } - let crc = -1; - - for (let index = 0; index < buf.length; index++) { - const byte = buf[index]; - crc = crcTable[(crc ^ byte) & 0xff] ^ (crc >>> 8); - } - return (crc ^ (-1)) >>> 0; -} - -const findAll = (regex, str, matches = []) => { +const findAll = (regex: RegExp, str: string, matches: string[][] = []) => { if (!regex.flags.includes('g')) { regex = new RegExp(regex.source, 'g'); } @@ -77,7 +68,7 @@ const findAll = (regex, str, matches = []) => { return matches; }; -const fromLine = (line, isFunction) => { +const fromLine = (line: string, isFunction?: boolean) => { const match = line.match(/([\w.]+)(?:#([0-9a-fA-F]+))?(?:\s{?\w+:[\w\d<>#.?!]+}?)*\s=\s([\w\d<>#.?]+);$/); if (!match) { // Probably "vector#1cb5c415 {t:Type} # [ t ] = Vector t;" @@ -85,7 +76,7 @@ const fromLine = (line, isFunction) => { } const argsMatch = findAll(/({)?(\w+):([\w\d<>#.?!]+)}?/, line); - const currentConfig = { + const currentConfig: GenerationEntryConfig = { name: match[1], constructorId: parseInt(match[2], 16), argsConfig: {}, @@ -140,17 +131,17 @@ const fromLine = (line, isFunction) => { return currentConfig; }; -function buildArgConfig(name, argType) { +function buildArgConfig(name: string, argType: string) { name = name === 'self' ? 'is_self' : name; // Default values - const currentConfig = { + const currentConfig: GenerationArgConfig = { isVector: false, isFlag: false, skipConstructorId: false, flagGroup: 0, flagIndex: -1, flagIndicator: true, - type: undefined, + type: '', useVectorId: undefined, }; @@ -191,7 +182,7 @@ function buildArgConfig(name, argType) { // See use_vector_id. An example of such case is ipPort in // help.configSpecial if (/^[a-z]$/.test(currentConfig.type.split('.') - .pop() + .pop()! .charAt(0)) ) { currentConfig.skipConstructorId = true; @@ -212,14 +203,14 @@ function buildArgConfig(name, argType) { return currentConfig; } -function* parseTl(content, methods = [], ignoreIds = CORE_TYPES) { +export function* parseTl(content: string, methods: any[] = [], ignoreIds = CORE_TYPES) { (methods || []).reduce((o, m) => ({ ...o, [m.name]: m, }), {}); - const objAll = []; - const objByName = {}; - const objByType = {}; + const objAll: GenerationEntryConfig[] = []; + const objByName: Record = {}; + const objByType: Record = {}; const file = content; @@ -263,7 +254,7 @@ function* parseTl(content, methods = [], ignoreIds = CORE_TYPES) { objByName[result.name] = result; objByType[result.result].push(result); } - } catch (e) { + } catch (e: any) { if (!e.toString() .includes('vector#1cb5c415')) { throw e; @@ -289,7 +280,7 @@ function* parseTl(content, methods = [], ignoreIds = CORE_TYPES) { } } -function serializeBytes(data) { +export function serializeBytes(data: Buffer | string | any) { if (!(data instanceof Buffer)) { if (typeof data === 'string') { data = Buffer.from(data); @@ -320,7 +311,7 @@ function serializeBytes(data) { return Buffer.concat(r); } -function serializeDate(dt) { +export function serializeDate(dt: Date | number) { if (!dt) { return Buffer.alloc(4) .fill(0); @@ -335,15 +326,3 @@ function serializeDate(dt) { } throw Error(`Cannot interpret "${dt}" as a date`); } - -module.exports = { - findAll, - parseTl, - buildArgConfig, - fromLine, - CORE_TYPES, - serializeDate, - serializeBytes, - snakeToCamelCase, - variableSnakeToCamelCase, -}; diff --git a/src/lib/gramjs/tl/index.js b/src/lib/gramjs/tl/index.js deleted file mode 100644 index df41fd228..000000000 --- a/src/lib/gramjs/tl/index.js +++ /dev/null @@ -1,13 +0,0 @@ -const api = require('./api'); -const { - serializeBytes, - serializeDate, -} = require('./generationHelpers'); - -module.exports = { - // TODO Refactor internal usages to always use `api`. - constructors: api, - requests: api, - serializeBytes, - serializeDate, -}; diff --git a/src/lib/gramjs/tl/index.ts b/src/lib/gramjs/tl/index.ts new file mode 100644 index 000000000..33c838014 --- /dev/null +++ b/src/lib/gramjs/tl/index.ts @@ -0,0 +1,8 @@ +import Api from './api'; +import { serializeBytes, serializeDate } from './generationHelpers'; + +export { + Api, + serializeBytes, + serializeDate, +}; diff --git a/src/lib/gramjs/tl/schemaTl.js b/src/lib/gramjs/tl/schemaTl.ts similarity index 94% rename from src/lib/gramjs/tl/schemaTl.js rename to src/lib/gramjs/tl/schemaTl.ts index cb1bffc41..a5a5a4b89 100644 --- a/src/lib/gramjs/tl/schemaTl.js +++ b/src/lib/gramjs/tl/schemaTl.ts @@ -1,4 +1,4 @@ -module.exports = `resPQ#05162463 nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:Vector = ResPQ; +export default `resPQ#05162463 nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:Vector = ResPQ; p_q_inner_data#83c95aec pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 = P_Q_inner_data; p_q_inner_data_dc#a9f55f95 pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 dc:int = P_Q_inner_data; p_q_inner_data_temp#3c6a84d4 pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 expires_in:int = P_Q_inner_data; @@ -35,7 +35,7 @@ rpc_answer_unknown#5e2ad36e = RpcDropAnswer; rpc_answer_dropped_running#cd78e586 = RpcDropAnswer; rpc_answer_dropped#a43ad8b7 msg_id:long seq_no:int bytes:int = RpcDropAnswer; future_salt#0949d9dc valid_since:int valid_until:int salt:long = FutureSalt; -future_salts#ae500895 req_msg_id:long now:int salts:vector = FutureSalts; +future_salts#ae500895 req_msg_id:long now:int salts:vector = FutureSalts; pong#347773c5 msg_id:long ping_id:long = Pong; destroy_session_ok#e22045fc session_id:long = DestroySessionRes; destroy_session_none#62d350c9 session_id:long = DestroySessionRes; diff --git a/src/lib/gramjs/tl/static/schema.tl b/src/lib/gramjs/tl/static/schema.tl index 08139deff..b34979ea7 100644 --- a/src/lib/gramjs/tl/static/schema.tl +++ b/src/lib/gramjs/tl/static/schema.tl @@ -69,7 +69,7 @@ rpc_answer_dropped_running#cd78e586 = RpcDropAnswer; rpc_answer_dropped#a43ad8b7 msg_id:long seq_no:int bytes:int = RpcDropAnswer; future_salt#0949d9dc valid_since:int valid_until:int salt:long = FutureSalt; -future_salts#ae500895 req_msg_id:long now:int salts:vector = FutureSalts; +future_salts#ae500895 req_msg_id:long now:int salts:vector = FutureSalts; pong#347773c5 msg_id:long ping_id:long = Pong; diff --git a/src/lib/gramjs/tl/types-generator/generate.js b/src/lib/gramjs/tl/types-generator/generate.ts similarity index 82% rename from src/lib/gramjs/tl/types-generator/generate.js rename to src/lib/gramjs/tl/types-generator/generate.ts index b94247cea..ba6552267 100644 --- a/src/lib/gramjs/tl/types-generator/generate.js +++ b/src/lib/gramjs/tl/types-generator/generate.ts @@ -1,8 +1,14 @@ -const path = require('path'); -const fs = require('fs'); +import fs from 'fs'; +import path from 'path'; -const { parseTl } = require('../generationHelpers'); -const templateFn = require('./template'); +import { parseTl } from '../generationHelpers'; +import templateFn from './template'; + +export type GenerationType = { + namespace?: string; + name: string; + constructors: Array; +}; const INPUT_FILE = path.resolve(__dirname, '../static/api.tl'); const SCHEMA_FILE = path.resolve(__dirname, '../static/schema.tl'); @@ -26,9 +32,9 @@ function main() { fs.writeFileSync(OUTPUT_FILE, generated); } -function extractParams(fileContent) { +function extractParams(fileContent: string) { const defInterator = parseTl(fileContent); - const types = {}; + const types: Record = {}; const constructors = []; const functions = []; diff --git a/src/lib/gramjs/tl/types-generator/template.js b/src/lib/gramjs/tl/types-generator/template.ts similarity index 54% rename from src/lib/gramjs/tl/types-generator/template.js rename to src/lib/gramjs/tl/types-generator/template.ts index 5fb2c8957..c2ca326d8 100644 --- a/src/lib/gramjs/tl/types-generator/template.js +++ b/src/lib/gramjs/tl/types-generator/template.ts @@ -1,44 +1,56 @@ +/* eslint-disable max-len */ +/* eslint-disable @typescript-eslint/indent */ +/* eslint-disable indent */ + +import type { GenerationArgConfig, GenerationEntryConfig } from '../generationHelpers'; +import type { GenerationType } from './generate'; + // Not sure what they are for. -const RAW_TYPES = new Set(['Bool', 'X']) +const RAW_TYPES = new Set(['Bool', 'X']); const FLAG_REGEX = /flags\d*/; -module.exports = ({ types, constructors, functions }) => { - function groupByKey(collection, key) { - return collection.reduce((byKey, member) => { - const keyValue = member[key] || '_' - - if (!byKey[keyValue]) { - byKey[keyValue] = [member] - } else { - byKey[keyValue].push(member) - } - - return byKey - }, {}) +const generate = ({ + types, + constructors, + functions, +}: { + types: GenerationType[]; + constructors: GenerationEntryConfig[]; + functions: GenerationEntryConfig[]; +}) => { + function groupByKey(list: T[], key: K) { + return list.reduce((previous, currentItem) => { + const group = currentItem[key] as string || '_'; + if (!previous[group]) previous[group] = []; + previous[group].push(currentItem); + return previous; + }, {} as Record); } - function isFlagArg(argName) { + function isFlagArg(argName: string) { return argName.match(FLAG_REGEX); } - function renderTypes(types, indent) { - return types.map(({ name, constructors }) => ` - ${!constructors.length ? '// ' : ''}export type Type${upperFirst(name)} = ${constructors.map((name) => name) + function renderTypes(arr: GenerationType[], indent: string) { + return arr.map(({ name, constructors: typeConstructors }) => ` + ${!typeConstructors.length ? '// ' : ''}export type Type${upperFirst(name)} = ${typeConstructors.map((n) => n) .join(' | ')}; `.trim()) - .join(`\n${indent}`) + .join(`\n${indent}`); } - function renderConstructors(constructors, indent) { - return constructors.map(({ name, argsConfig }) => { - const argKeys = Object.keys(argsConfig) + function renderConstructors(arr: GenerationEntryConfig[], indent: string) { + return arr.map(({ name, argsConfig }) => { + const argKeys = Object.keys(argsConfig); if (!argKeys.length) { - return `export class ${upperFirst(name)} extends VirtualClass {};` + return `export class ${upperFirst(name)} extends VirtualClass { +${indent} static fromReader(reader: Reader): ${upperFirst(name)}; +${indent}}`; } - let hasRequiredArgs = argKeys.some((argName) => !isFlagArg(argName) && !argsConfig[argName].isFlag) + const hasRequiredArgs = argKeys.some((argName) => !isFlagArg(argName) && !argsConfig[argName].isFlag); return ` export class ${upperFirst(name)} extends VirtualClass<{ @@ -47,27 +59,28 @@ ${indent} ${Object.keys(argsConfig) ${renderArg(argName, argsConfig[argName])}; `.trim()) .join(`\n${indent} `)} -${indent}}${!hasRequiredArgs ? ` | void` : ''}> { +${indent}}${!hasRequiredArgs ? ' | void' : ''}> { ${indent} ${Object.keys(argsConfig) .map((argName) => ` ${renderArg(argName, argsConfig[argName])}; `.trim()) .join(`\n${indent} `)} -${indent}};`.trim() +${indent} static fromReader(reader: Reader): ${upperFirst(name)}; +${indent}}`.trim(); }) - .join(`\n${indent}`) + .join(`\n${indent}`); } - function renderRequests(requests, indent) { + function renderRequests(requests: GenerationEntryConfig[], indent: string) { return requests.map(({ name, argsConfig, result }) => { - const argKeys = Object.keys(argsConfig) + const argKeys = Object.keys(argsConfig); const renderedResult = renderResult(result); if (!argKeys.length) { - return `export class ${upperFirst(name)} extends Request {};` + return `export class ${upperFirst(name)} extends Request {}`; } - let hasRequiredArgs = argKeys.some((argName) => !isFlagArg(argName) && !argsConfig[argName].isFlag) + const hasRequiredArgs = argKeys.some((argName) => !isFlagArg(argName) && !argsConfig[argName].isFlag); return ` export class ${upperFirst(name)} extends Request ` ${renderArg(argName, argsConfig[argName])}; `.trim()) .join(`\n${indent} `)} -${indent}}${!hasRequiredArgs ? ` | void` : ''}>, ${renderedResult}> { +${indent}}${!hasRequiredArgs ? ' | void' : ''}>, ${renderedResult}> { ${indent} ${argKeys.map((argName) => ` ${renderArg(argName, argsConfig[argName])}; `.trim()) .join(`\n${indent} `)} -${indent}};`.trim() +${indent}}`.trim(); }) - .join(`\n${indent}`) + .join(`\n${indent}`); } - function renderResult(result) { - const vectorMatch = result.match(/[Vv]ector<([\w\d.]+)>/) - const isVector = Boolean(vectorMatch) - const scalarValue = isVector ? vectorMatch[1] : result - const isTlType = Boolean(scalarValue.match(/^[A-Z]/)) || scalarValue.includes('.') + function renderResult(result: string) { + const vectorMatch = result.match(/[Vv]ector<([\w\d.]+)>/); + const isVector = Boolean(vectorMatch); + const scalarValue = isVector ? vectorMatch[1] : result; + const isTlType = Boolean(scalarValue.match(/^[A-Z]/)) || scalarValue.includes('.'); - return renderValueType(scalarValue, isVector, isTlType) + return renderValueType(scalarValue, isVector, isTlType); } - function renderArg(argName, argConfig) { + function renderArg(argName: string, argConfig: GenerationArgConfig) { const { - isVector, isFlag, skipConstructorId, type - } = argConfig + isVector, isFlag, skipConstructorId, type, + } = argConfig; - const valueType = renderValueType(type, isVector, !skipConstructorId) + const valueType = renderValueType(type, isVector, !skipConstructorId); - return `${isFlagArg(argName) ? '// ' : ''}${argName}${isFlag ? '?' : ''}: ${valueType}` + return `${isFlagArg(argName) ? '// ' : ''}${argName}${isFlag ? '?' : ''}: ${valueType}`; } - function renderValueType(type, isVector, isTlType) { + function renderValueType(type: string, isVector?: boolean, isTlType?: boolean) { if (RAW_TYPES.has(type)) { return isVector ? `${type}[]` : type; } - let resType + let resType; if (typeof type === 'string' && isTlType) { resType = renderTypeName(type); @@ -124,17 +137,17 @@ ${indent}};`.trim() return resType; } - function renderTypeName(typeName) { - return typeName.includes('.') ? typeName.replace('.', '.Type') : `Api.Type${typeName}` + function renderTypeName(typeName: string) { + return typeName.includes('.') ? typeName.replace('.', '.Type') : `Api.Type${typeName}`; } - function upperFirst(str) { - return `${str[0].toUpperCase()}${str.slice(1)}` + function upperFirst(str: string) { + return `${str[0].toUpperCase()}${str.slice(1)}`; } - const typesByNs = groupByKey(types, 'namespace') - const constructorsByNs = groupByKey(constructors, 'namespace') - const requestsByNs = groupByKey(functions, 'namespace') + const typesByNs = groupByKey(types, 'namespace'); + const constructorsByNs = groupByKey(constructors, 'namespace'); + const requestsByNs = groupByKey(functions, 'namespace'); // language=TypeScript return ` @@ -149,15 +162,17 @@ namespace Api { type AnyClass = new (...args: any[]) => any; type I = InstanceType; type ValuesOf = T[keyof T]; - type AnyLiteral = Record; + type AnyLiteral = Record | void; type Reader = any; // To be defined. type Client = any; // To be defined. type Utils = any; // To be defined. - type X = AnyLiteral; + type X = unknown; + type Type = unknown; type Bool = boolean; type int = number; + type double = number; type int128 = BigInteger; type int256 = BigInteger; type long = BigInteger; @@ -170,8 +185,6 @@ namespace Api { static classType: 'constructor' | 'request'; static serializeBytes(data: Buffer | string): Buffer; - static serializeDate(date: Date | number): Buffer; - static fromReader(reader: Reader): VirtualClass; getBytes(): Buffer; CONSTRUCTOR_ID: number; @@ -184,43 +197,44 @@ namespace Api { class Request extends VirtualClass> { static readResult(reader: Reader): Buffer; - static resolve(client: Client, utils: Utils): Promise; __response: Response; } ${renderTypes(typesByNs._, ' ')} ${Object.keys(typesByNs) - .map(namespace => namespace !== '_' ? ` + .map((namespace) => (namespace !== '_' ? ` export namespace ${namespace} { ${renderTypes(typesByNs[namespace], ' ')} - }` : '') + }` : '')) .join('\n')} ${renderConstructors(constructorsByNs._, ' ')} ${Object.keys(constructorsByNs) - .map(namespace => namespace !== '_' ? ` + .map((namespace) => (namespace !== '_' ? ` export namespace ${namespace} { ${renderConstructors(constructorsByNs[namespace], ' ')} - }` : '') + }` : '')) .join('\n')} ${renderRequests(requestsByNs._, ' ')} ${Object.keys(requestsByNs) - .map(namespace => namespace !== '_' ? ` + .map((namespace) => (namespace !== '_' ? ` export namespace ${namespace} { ${renderRequests(requestsByNs[namespace], ' ')} - }` : '') + }` : '')) .join('\n')} export type AnyRequest = ${requestsByNs._.map(({ name }) => upperFirst(name)) .join(' | ')} | ${Object.keys(requestsByNs) - .filter(ns => ns !== '_') - .map(ns => requestsByNs[ns].map(({ name }) => `${ns}.${upperFirst(name)}`) + .filter((ns) => ns !== '_') + .map((ns) => requestsByNs[ns].map(({ name }) => `${ns}.${upperFirst(name)}`) .join(' | ')) .join('\n | ')}; } -` -} +`; +}; + +export default generate; diff --git a/src/lib/gramjs/types.ts b/src/lib/gramjs/types.ts new file mode 100644 index 000000000..50aaf26cc --- /dev/null +++ b/src/lib/gramjs/types.ts @@ -0,0 +1,25 @@ +import type Api from './tl/api'; + +export type Entity = Api.TypeUser | Api.TypeChat; +export type FullEntity = + | Api.UserFull + | Api.messages.ChatFull + | Api.ChatFull + | Api.ChannelFull; + +export type EntityLike = + | bigInt.BigInteger + | string + | Api.TypePeer + | Api.TypeInputPeer + | Entity + | FullEntity + | Api.TypeInputChannel + | Api.TypeInputUser; + +export interface SessionData { + mainDcId: number; + keys: Record; + hashes: Record; + isTest?: true; +} diff --git a/src/lib/secret-sauce/parseSdp.ts b/src/lib/secret-sauce/parseSdp.ts index 2083a02c6..076b16372 100644 --- a/src/lib/secret-sauce/parseSdp.ts +++ b/src/lib/secret-sauce/parseSdp.ts @@ -50,12 +50,12 @@ export default (sessionDescription: RTCSessionDescriptionInit, isP2p = false): J const parameters = sections[sectionName].filter((l) => l.startsWith('a=fmtp')).map((l) => { const [, id, data] = l.match(/:(\d+)\s(.+)/) || []; - const d = data.split(';').reduce((acc: Record, q) => { + const d = data?.split(';').reduce((acc: Record, q) => { const [name, value] = q.split('='); acc[name] = value; return acc; }, {}); - if (Object.values(d).some((z) => !z)) return undefined; + if (!d || Object.values(d).some((z) => !z)) return undefined; return { id: Number(id), data: d }; }).filter(Boolean);