build: fixed scripts, eslintignore, fixed linter warnings and re-formatted with prettier

This commit is contained in:
teidesu 2021-06-06 15:20:41 +03:00
parent 5e05b099ed
commit ae2dbcf03f
146 changed files with 882 additions and 552 deletions

View file

@ -2,3 +2,11 @@ private/
docs/ docs/
dist/ dist/
scripts/ scripts/
packages/tl/errors.js
packages/tl/errors.d.ts
packages/tl/index.js
packages/tl/index.d.ts
packages/tl/binary/reader.js
packages/tl/binary/writer.js
packages/tl/binary/rsa-keys.js

View file

@ -6,13 +6,10 @@
"license": "MIT", "license": "MIT",
"author": "Alisa Sireneva <me@tei.su>", "author": "Alisa Sireneva <me@tei.su>",
"scripts": { "scripts": {
"test": "tsc && mocha dist/tests/**/*.spec.js", "test": "lerna run test",
"build": "tsc", "build": "lerna run build",
"lint": "eslint packages/**/*.ts", "lint": "eslint packages/**/*.ts",
"generate-schema": "node scripts/generate-schema.js", "format": "prettier --write packages/**/*.ts"
"generate-code": "node packages/client/scripts/generate-client.js && node scripts/generate-types.js && node scripts/generate-binary-reader.js && node scripts/generate-binary-writer.js && node scripts/post-build.js",
"generate-all": "npm run generate-schema && npm run generate-code",
"build:doc": "node packages/client/scripts/generate-client.js && typedoc"
}, },
"dependencies": { "dependencies": {
"big-integer": "1.6.48", "big-integer": "1.6.48",

View file

@ -164,7 +164,6 @@ import {
Dialog, Dialog,
FileDownloadParameters, FileDownloadParameters,
GameHighScore, GameHighScore,
InputChatPermissions,
InputFileLike, InputFileLike,
InputInlineResult, InputInlineResult,
InputMediaLike, InputMediaLike,
@ -1444,6 +1443,7 @@ export interface TelegramClient extends BaseTelegramClient {
* > into memory at once. This might cause an issue, so use wisely! * > into memory at once. This might cause an issue, so use wisely!
* *
* @param params File download parameters * @param params File download parameters
*/ */
downloadAsBuffer(params: FileDownloadParameters): Promise<Buffer> downloadAsBuffer(params: FileDownloadParameters): Promise<Buffer>
/** /**
@ -1452,6 +1452,7 @@ export interface TelegramClient extends BaseTelegramClient {
* *
* @param filename Local file name to which the remote file will be downloaded * @param filename Local file name to which the remote file will be downloaded
* @param params File download parameters * @param params File download parameters
*/ */
downloadToFile( downloadToFile(
filename: string, filename: string,
@ -1463,6 +1464,7 @@ export interface TelegramClient extends BaseTelegramClient {
* consecutive. * consecutive.
* *
* @param params Download parameters * @param params Download parameters
*/ */
downloadAsIterable( downloadAsIterable(
params: FileDownloadParameters params: FileDownloadParameters
@ -1472,6 +1474,7 @@ export interface TelegramClient extends BaseTelegramClient {
* streaming file contents. * streaming file contents.
* *
* @param params File download parameters * @param params File download parameters
*/ */
downloadAsStream(params: FileDownloadParameters): Readable downloadAsStream(params: FileDownloadParameters): Readable
/** /**

View file

@ -0,0 +1,6 @@
module.exports = {
rules: {
// common when using preprocessor directives
'@typescript-eslint/no-unused-vars': 'off',
}
}

View file

@ -13,7 +13,6 @@ import {
ChatPreview, ChatPreview,
ChatMember, ChatMember,
Dialog, Dialog,
InputChatPermissions,
TermsOfService, TermsOfService,
SentCode, SentCode,
MaybeDynamic, MaybeDynamic,

View file

@ -55,6 +55,6 @@ export async function answerCallbackQuery(
cacheTime: params.cacheTime ?? 0, cacheTime: params.cacheTime ?? 0,
alert: params.alert, alert: params.alert,
message: params.text, message: params.text,
url: params.url url: params.url,
}) })
} }

View file

@ -93,7 +93,9 @@ export async function answerInlineQuery(
): Promise<void> { ): Promise<void> {
if (!params) params = {} if (!params) params = {}
const tlResults = await Promise.all(results.map(it => BotInline._convertToTl(this, it, params!.parseMode))) const tlResults = await Promise.all(
results.map((it) => BotInline._convertToTl(this, it, params!.parseMode))
)
await this.call({ await this.call({
_: 'messages.setInlineBotResults', _: 'messages.setInlineBotResults',
@ -103,10 +105,12 @@ export async function answerInlineQuery(
gallery: params.gallery, gallery: params.gallery,
private: params.private, private: params.private,
nextOffset: params.nextOffset, nextOffset: params.nextOffset,
switchPm: params.switchPm ? { switchPm: params.switchPm
_: 'inlineBotSwitchPM', ? {
text: params.switchPm.text, _: 'inlineBotSwitchPM',
startParam: params.switchPm.parameter text: params.switchPm.text,
} : undefined startParam: params.switchPm.parameter,
}
: undefined,
}) })
} }

View file

@ -45,7 +45,7 @@ export async function addChatMembers(
const updates = await this.call({ const updates = await this.call({
_: 'channels.inviteToChannel', _: 'channels.inviteToChannel',
channel: normalizeToInputChannel(chat), channel: normalizeToInputChannel(chat),
users: await this.resolvePeerMany( users: await this.resolvePeerMany(
users as InputPeerLike[], users as InputPeerLike[],
normalizeToInputUser normalizeToInputUser
), ),

View file

@ -21,13 +21,13 @@ export async function archiveChats(
folderPeers.push({ folderPeers.push({
_: 'inputFolderPeer', _: 'inputFolderPeer',
peer: await this.resolvePeer(chat), peer: await this.resolvePeer(chat),
folderId: 1 folderId: 1,
}) })
} }
const updates = await this.call({ const updates = await this.call({
_: 'folders.editPeerFolders', _: 'folders.editPeerFolders',
folderPeers folderPeers,
}) })
this._handleUpdate(updates) this._handleUpdate(updates)
} }

View file

@ -24,7 +24,7 @@ export async function createGroup(
): Promise<Chat> { ): Promise<Chat> {
if (!Array.isArray(users)) users = [users] if (!Array.isArray(users)) users = [users]
const peers = await this.resolvePeerMany( const peers = await this.resolvePeerMany(
users as InputPeerLike[], users as InputPeerLike[],
normalizeToInputUser normalizeToInputUser
) )
@ -32,7 +32,7 @@ export async function createGroup(
const res = await this.call({ const res = await this.call({
_: 'messages.createChat', _: 'messages.createChat',
title, title,
users: peers users: peers,
}) })
assertIsUpdatesGroup('messages.createChat', res) assertIsUpdatesGroup('messages.createChat', res)

View file

@ -18,7 +18,7 @@ export async function createSupergroup(
_: 'channels.createChannel', _: 'channels.createChannel',
title, title,
about: description, about: description,
megagroup: true megagroup: true,
}) })
assertIsUpdatesGroup('channels.createChannel', res) assertIsUpdatesGroup('channels.createChannel', res)

View file

@ -9,13 +9,16 @@ import { normalizeToInputChannel } from '../../utils/peer-utils'
* @param chatId Chat ID or username * @param chatId Chat ID or username
* @internal * @internal
*/ */
export async function deleteChannel(this: TelegramClient, chatId: InputPeerLike): Promise<void> { export async function deleteChannel(
this: TelegramClient,
chatId: InputPeerLike
): Promise<void> {
const peer = normalizeToInputChannel(await this.resolvePeer(chatId)) const peer = normalizeToInputChannel(await this.resolvePeer(chatId))
if (!peer) throw new MtCuteInvalidPeerTypeError(chatId, 'channel') if (!peer) throw new MtCuteInvalidPeerTypeError(chatId, 'channel')
const res = await this.call({ const res = await this.call({
_: 'channels.deleteChannel', _: 'channels.deleteChannel',
channel: peer channel: peer,
}) })
this._handleUpdate(res) this._handleUpdate(res)
} }

View file

@ -32,12 +32,18 @@ export async function deleteHistory(
justClear: mode === 'clear', justClear: mode === 'clear',
revoke: mode === 'revoke', revoke: mode === 'revoke',
peer, peer,
maxId maxId,
}) })
const channel = normalizeToInputChannel(peer) const channel = normalizeToInputChannel(peer)
if (channel) { if (channel) {
this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount, (channel as tl.RawInputChannel).channelId)) this._handleUpdate(
createDummyUpdate(
res.pts,
res.ptsCount,
(channel as tl.RawInputChannel).channelId
)
)
} else { } else {
this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount)) this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount))
} }

View file

@ -1,7 +1,10 @@
import { TelegramClient } from '../../client' import { TelegramClient } from '../../client'
import { InputPeerLike, MtCuteInvalidPeerTypeError } from '../../types' import { InputPeerLike, MtCuteInvalidPeerTypeError } from '../../types'
import { tl } from '@mtcute/tl' import { tl } from '@mtcute/tl'
import { normalizeToInputChannel, normalizeToInputUser } from '../../utils/peer-utils' import {
normalizeToInputChannel,
normalizeToInputUser,
} from '../../utils/peer-utils'
/** /**
* Edit supergroup/channel admin rights of a user. * Edit supergroup/channel admin rights of a user.
@ -20,12 +23,10 @@ export async function editAdminRights(
rank = '' rank = ''
): Promise<void> { ): Promise<void> {
const chat = normalizeToInputChannel(await this.resolvePeer(chatId)) const chat = normalizeToInputChannel(await this.resolvePeer(chatId))
if (!chat) if (!chat) throw new MtCuteInvalidPeerTypeError(chatId, 'channel')
throw new MtCuteInvalidPeerTypeError(chatId, 'channel')
const user = normalizeToInputUser(await this.resolvePeer(userId)) const user = normalizeToInputUser(await this.resolvePeer(userId))
if (!user) if (!user) throw new MtCuteInvalidPeerTypeError(userId, 'user')
throw new MtCuteInvalidPeerTypeError(userId, 'user')
const res = await this.call({ const res = await this.call({
_: 'channels.editAdmin', _: 'channels.editAdmin',
@ -33,9 +34,9 @@ export async function editAdminRights(
userId: user, userId: user,
adminRights: { adminRights: {
_: 'chatAdminRights', _: 'chatAdminRights',
...rights ...rights,
}, },
rank rank,
}) })
this._handleUpdate(res) this._handleUpdate(res)

View file

@ -97,10 +97,7 @@ export async function* getChatEventLog(
const chunkSize = Math.min(params.chunkSize ?? 100, total) const chunkSize = Math.min(params.chunkSize ?? 100, total)
const admins: tl.TypeInputUser[] | undefined = params.users const admins: tl.TypeInputUser[] | undefined = params.users
? await this.resolvePeerMany( ? await this.resolvePeerMany(params.users, normalizeToInputUser)
params.users,
normalizeToInputUser
)
: undefined : undefined
let serverFilter: let serverFilter:

View file

@ -26,9 +26,7 @@ export async function getChatPreview(
}) })
if (res._ !== 'chatInvite') { if (res._ !== 'chatInvite') {
throw new MtCuteNotFoundError( throw new MtCuteNotFoundError(`You have already joined this chat!`)
`You have already joined this chat!`
)
} }
return new ChatPreview(this, res, inviteLink) return new ChatPreview(this, res, inviteLink)

View file

@ -31,19 +31,23 @@ export async function getNearbyChats(
if (!res.updates.length) return [] if (!res.updates.length) return []
assertTypeIs('contacts.getLocated (@ .updates[0])', res.updates[0], 'updatePeerLocated') assertTypeIs(
'contacts.getLocated (@ .updates[0])',
res.updates[0],
'updatePeerLocated'
)
const chats = res.chats.map((it) => new Chat(this, it)) const chats = res.chats.map((it) => new Chat(this, it))
const index: Record<number, Chat> = {} const index: Record<number, Chat> = {}
chats.forEach((c) => index[c.id] = c) chats.forEach((c) => (index[c.id] = c))
res.updates[0].peers.forEach((peer) => { res.updates[0].peers.forEach((peer) => {
if (peer._ === 'peerSelfLocated') return if (peer._ === 'peerSelfLocated') return
const id = getMarkedPeerId(peer.peer) const id = getMarkedPeerId(peer.peer)
if (index[id]) { if (index[id]) {
(index[id] as tl.Mutable<Chat>).distance = peer.distance ;(index[id] as tl.Mutable<Chat>).distance = peer.distance
} }
}) })

View file

@ -41,7 +41,7 @@ export async function* iterChatMembers(
offset, offset,
limit, limit,
query: params.query, query: params.query,
type: params.type type: params.type,
}) })
if (!members.length) break if (!members.length) break

View file

@ -17,6 +17,6 @@ export async function markChatUnread(
_: 'inputDialogPeer', _: 'inputDialogPeer',
peer: await this.resolvePeer(chatId), peer: await this.resolvePeer(chatId),
}, },
unread: true unread: true,
}) })
} }

View file

@ -20,13 +20,13 @@ export async function saveDraft(
await this.call({ await this.call({
_: 'messages.saveDraft', _: 'messages.saveDraft',
peer, peer,
...draft ...draft,
}) })
} else { } else {
await this.call({ await this.call({
_: 'messages.saveDraft', _: 'messages.saveDraft',
peer, peer,
message: '' message: '',
}) })
} }
} }

View file

@ -29,8 +29,8 @@ export async function setChatDefaultPermissions(
bannedRights: { bannedRights: {
_: 'chatBannedRights', _: 'chatBannedRights',
untilDate: 0, untilDate: 0,
...restrictions ...restrictions,
} },
}) })
assertIsUpdatesGroup('messages.editChatDefaultBannedRights', res) assertIsUpdatesGroup('messages.editChatDefaultBannedRights', res)

View file

@ -1,8 +1,5 @@
import { TelegramClient } from '../../client' import { TelegramClient } from '../../client'
import { import { InputPeerLike, MtCuteInvalidPeerTypeError } from '../../types'
InputPeerLike,
MtCuteInvalidPeerTypeError,
} from '../../types'
import { import {
isInputPeerChannel, isInputPeerChannel,
isInputPeerChat, isInputPeerChat,
@ -30,13 +27,13 @@ export async function setChatTitle(
res = await this.call({ res = await this.call({
_: 'messages.editChatTitle', _: 'messages.editChatTitle',
chatId: chat.chatId, chatId: chat.chatId,
title title,
}) })
} else if (isInputPeerChannel(chat)) { } else if (isInputPeerChannel(chat)) {
res = await this.call({ res = await this.call({
_: 'channels.editTitle', _: 'channels.editTitle',
channel: normalizeToInputChannel(chat), channel: normalizeToInputChannel(chat),
title title,
}) })
} else throw new MtCuteInvalidPeerTypeError(chatId, 'chat or channel') } else throw new MtCuteInvalidPeerTypeError(chatId, 'chat or channel')

View file

@ -1,8 +1,5 @@
import { TelegramClient } from '../../client' import { TelegramClient } from '../../client'
import { import { InputPeerLike, MtCuteInvalidPeerTypeError } from '../../types'
InputPeerLike,
MtCuteInvalidPeerTypeError,
} from '../../types'
import { normalizeToInputChannel } from '../../utils/peer-utils' import { normalizeToInputChannel } from '../../utils/peer-utils'
/** /**
@ -20,12 +17,11 @@ export async function setChatUsername(
username: string | null username: string | null
): Promise<void> { ): Promise<void> {
const chat = normalizeToInputChannel(await this.resolvePeer(chatId)) const chat = normalizeToInputChannel(await this.resolvePeer(chatId))
if (!chat) if (!chat) throw new MtCuteInvalidPeerTypeError(chatId, 'channel')
throw new MtCuteInvalidPeerTypeError(chatId, 'channel')
await this.call({ await this.call({
_: 'channels.updateUsername', _: 'channels.updateUsername',
channel: chat, channel: chat,
username: username || '' username: username || '',
}) })
} }

View file

@ -23,7 +23,7 @@ export async function setSlowMode(
const res = await this.call({ const res = await this.call({
_: 'channels.toggleSlowMode', _: 'channels.toggleSlowMode',
channel: chat, channel: chat,
seconds seconds,
}) })
this._handleUpdate(res) this._handleUpdate(res)
} }

View file

@ -21,13 +21,13 @@ export async function unarchiveChats(
folderPeers.push({ folderPeers.push({
_: 'inputFolderPeer', _: 'inputFolderPeer',
peer: await this.resolvePeer(chat), peer: await this.resolvePeer(chat),
folderId: 0 folderId: 0,
}) })
} }
const res = await this.call({ const res = await this.call({
_: 'folders.editPeerFolders', _: 'folders.editPeerFolders',
folderPeers folderPeers,
}) })
this._handleUpdate(res) this._handleUpdate(res)
} }

View file

@ -1,5 +1,10 @@
import { TelegramClient } from '../../client' import { TelegramClient } from '../../client'
import { InputPeerLike, MtCuteInvalidPeerTypeError, MtCuteTypeAssertionError, User } from '../../types' import {
InputPeerLike,
MtCuteInvalidPeerTypeError,
MtCuteTypeAssertionError,
User,
} from '../../types'
import { normalizeToInputUser } from '../../utils/peer-utils' import { normalizeToInputUser } from '../../utils/peer-utils'
import { tl } from '@mtcute/tl' import { tl } from '@mtcute/tl'
import { assertIsUpdatesGroup } from '../../utils/updates-utils' import { assertIsUpdatesGroup } from '../../utils/updates-utils'
@ -46,7 +51,7 @@ export async function addContact(
firstName: params.firstName, firstName: params.firstName,
lastName: params.lastName ?? '', lastName: params.lastName ?? '',
phone: params.phone ?? '', phone: params.phone ?? '',
addPhonePrivacyException: !!params.sharePhone addPhonePrivacyException: !!params.sharePhone,
}) })
assertIsUpdatesGroup('contacts.addContact', res) assertIsUpdatesGroup('contacts.addContact', res)

View file

@ -1,6 +1,11 @@
import { TelegramClient } from '../../client' import { TelegramClient } from '../../client'
import { MaybeArray } from '@mtcute/core' import { MaybeArray } from '@mtcute/core'
import { InputPeerLike, MtCuteInvalidPeerTypeError, MtCuteTypeAssertionError, User } from '../../types' import {
InputPeerLike,
MtCuteInvalidPeerTypeError,
MtCuteTypeAssertionError,
User,
} from '../../types'
import { normalizeToInputUser } from '../../utils/peer-utils' import { normalizeToInputUser } from '../../utils/peer-utils'
import { tl } from '@mtcute/tl' import { tl } from '@mtcute/tl'
import { assertIsUpdatesGroup } from '../../utils/updates-utils' import { assertIsUpdatesGroup } from '../../utils/updates-utils'
@ -41,7 +46,7 @@ export async function deleteContacts(
const single = !Array.isArray(userIds) const single = !Array.isArray(userIds)
if (single) userIds = [userIds as InputPeerLike] if (single) userIds = [userIds as InputPeerLike]
const inputPeers = await this.resolvePeerMany( const inputPeers = await this.resolvePeerMany(
userIds as InputPeerLike[], userIds as InputPeerLike[],
normalizeToInputUser normalizeToInputUser
) )
@ -54,7 +59,7 @@ export async function deleteContacts(
const res = await this.call({ const res = await this.call({
_: 'contacts.deleteContacts', _: 'contacts.deleteContacts',
id: inputPeers id: inputPeers,
}) })
assertIsUpdatesGroup('contacts.deleteContacts', res) assertIsUpdatesGroup('contacts.deleteContacts', res)
@ -63,7 +68,7 @@ export async function deleteContacts(
this._handleUpdate(res) this._handleUpdate(res)
const users = res.users.map(user => new User(this, user)) const users = res.users.map((user) => new User(this, user))
return single ? users[0] : users return single ? users[0] : users
} }

View file

@ -7,12 +7,10 @@ import { tl } from '@mtcute/tl'
* Get list of contacts from your Telegram contacts list. * Get list of contacts from your Telegram contacts list.
* @internal * @internal
*/ */
export async function getContacts( export async function getContacts(this: TelegramClient): Promise<User[]> {
this: TelegramClient
): Promise<User[]> {
const res = await this.call({ const res = await this.call({
_: 'contacts.getContacts', _: 'contacts.getContacts',
hash: 0 hash: 0,
}) })
assertTypeIs('getContacts', res, 'contacts.contacts') assertTypeIs('getContacts', res, 'contacts.contacts')

View file

@ -36,13 +36,13 @@ export async function createFolder(
includePeers: [], includePeers: [],
excludePeers: [], excludePeers: [],
...folder, ...folder,
id id,
} }
await this.call({ await this.call({
_: 'messages.updateDialogFilter', _: 'messages.updateDialogFilter',
id, id,
filter filter,
}) })
return filter return filter

View file

@ -21,21 +21,22 @@ export async function editFolder(
): Promise<tl.RawDialogFilter> { ): Promise<tl.RawDialogFilter> {
if (typeof folder === 'number' || typeof folder === 'string') { if (typeof folder === 'number' || typeof folder === 'string') {
const old = await this.getFolders() const old = await this.getFolders()
const found = old.find(it => it.id === folder || it.title === folder) const found = old.find((it) => it.id === folder || it.title === folder)
if (!found) throw new MtCuteArgumentError(`Could not find a folder ${folder}`) if (!found)
throw new MtCuteArgumentError(`Could not find a folder ${folder}`)
folder = found folder = found
} }
const filter: tl.RawDialogFilter = { const filter: tl.RawDialogFilter = {
...folder, ...folder,
...modification ...modification,
} }
await this.call({ await this.call({
_: 'messages.updateDialogFilter', _: 'messages.updateDialogFilter',
id: folder.id, id: folder.id,
filter filter,
}) })
return filter return filter

View file

@ -25,11 +25,13 @@ export async function findFolder(
const folders = await this.getFolders() const folders = await this.getFolders()
return folders.find((it) => { return (
if (params.id && it.id !== params.id) return false folders.find((it) => {
if (params.title && it.title !== params.title) return false if (params.id && it.id !== params.id) return false
if (params.emoji && it.emoticon !== params.emoji) return false if (params.title && it.title !== params.title) return false
if (params.emoji && it.emoticon !== params.emoji) return false
return true return true
}) ?? null }) ?? null
)
} }

View file

@ -132,7 +132,9 @@ export async function* getDialogs(
(it) => it.id === params!.folder || it.title === params!.folder (it) => it.id === params!.folder || it.title === params!.folder
) )
if (!found) if (!found)
throw new MtCuteArgumentError(`Could not find folder ${params.folder}`) throw new MtCuteArgumentError(
`Could not find folder ${params.folder}`
)
filters = found filters = found
} else { } else {
@ -143,7 +145,7 @@ export async function* getDialogs(
if (filters) { if (filters) {
filters = { filters = {
...filters, ...filters,
...params.filter ...params.filter,
} }
} else { } else {
filters = { filters = {
@ -153,7 +155,7 @@ export async function* getDialogs(
pinnedPeers: [], pinnedPeers: [],
includePeers: [], includePeers: [],
excludePeers: [], excludePeers: [],
...params.filter ...params.filter,
} }
} }
} }
@ -164,11 +166,13 @@ export async function* getDialogs(
_: 'messages.getPeerDialogs', _: 'messages.getPeerDialogs',
peers: filters.pinnedPeers.map((peer) => ({ peers: filters.pinnedPeers.map((peer) => ({
_: 'inputDialogPeer', _: 'inputDialogPeer',
peer peer,
})) })),
}) })
res.dialogs.forEach((dialog: tl.Mutable<tl.TypeDialog>) => dialog.pinned = true) res.dialogs.forEach(
(dialog: tl.Mutable<tl.TypeDialog>) => (dialog.pinned = true)
)
return res return res
} }
@ -243,11 +247,11 @@ export async function* getDialogs(
} }
const filterFolder = filters const filterFolder = filters
// if pinned is `only`, this wouldn't be reached ? // if pinned is `only`, this wouldn't be reached
// if pinned is `exclude`, we want to exclude them // if pinned is `exclude`, we want to exclude them
// if pinned is `include`, we already yielded them, so we also want to exclude them // if pinned is `include`, we already yielded them, so we also want to exclude them
// if pinned is `keep`, we want to keep them // if pinned is `keep`, we want to keep them
? Dialog.filterFolder(filters, pinned !== 'keep') Dialog.filterFolder(filters, pinned !== 'keep')
: undefined : undefined
const folderId = const folderId =

View file

@ -5,8 +5,10 @@ import { tl } from '@mtcute/tl'
* Get list of folders. * Get list of folders.
* @internal * @internal
*/ */
export async function getFolders(this: TelegramClient): Promise<tl.RawDialogFilter[]> { export async function getFolders(
this: TelegramClient
): Promise<tl.RawDialogFilter[]> {
return this.call({ return this.call({
_: 'messages.getDialogFilters' _: 'messages.getDialogFilters',
}) })
} }

View file

@ -8,7 +8,11 @@ import {
FileDownloadParameters, FileDownloadParameters,
FileLocation, FileLocation,
} from '../../types' } from '../../types'
import { fileIdToInputFileLocation, fileIdToInputWebFileLocation, parseFileId } from '@mtcute/file-id' import {
fileIdToInputFileLocation,
fileIdToInputWebFileLocation,
parseFileId,
} from '@mtcute/file-id'
/** /**
* Download a file and return it as an iterable, which yields file contents * Download a file and return it as an iterable, which yields file contents
@ -84,14 +88,19 @@ export async function* downloadAsIterable(
} }
const requestCurrent = async (): Promise<Buffer> => { const requestCurrent = async (): Promise<Buffer> => {
let result: tl.RpcCallReturn['upload.getFile'] | tl.RpcCallReturn['upload.getWebFile'] let result:
| tl.RpcCallReturn['upload.getFile']
| tl.RpcCallReturn['upload.getWebFile']
try { try {
result = await this.call({ result = await this.call(
_: isWeb ? 'upload.getWebFile' : 'upload.getFile', {
location: location as any, _: isWeb ? 'upload.getWebFile' : 'upload.getFile',
offset, location: location as any,
limit: chunkSize offset,
}, { connection }) limit: chunkSize,
},
{ connection }
)
} catch (e) { } catch (e) {
if (e.constructor === FileMigrateError) { if (e.constructor === FileMigrateError) {
connection = this._downloadConnections[e.newDc] connection = this._downloadConnections[e.newDc]
@ -116,7 +125,11 @@ export async function* downloadAsIterable(
) )
} }
if (result._ === 'upload.webFile' && result.size && limit === Infinity) { if (
result._ === 'upload.webFile' &&
result.size &&
limit === Infinity
) {
limit = result.size limit = result.size
} }

View file

@ -11,16 +11,20 @@ export async function _normalizeFileToDocument(
file: InputFileLike | tl.TypeInputDocument, file: InputFileLike | tl.TypeInputDocument,
params: { params: {
progressCallback?: (uploaded: number, total: number) => void progressCallback?: (uploaded: number, total: number) => void
}, }
): Promise<tl.TypeInputDocument> { ): Promise<tl.TypeInputDocument> {
if (typeof file === 'object' && tl.isAnyInputDocument(file)) { if (typeof file === 'object' && tl.isAnyInputDocument(file)) {
return file return file
} }
const media = await this._normalizeInputMedia({ const media = await this._normalizeInputMedia(
type: 'document', {
file, type: 'document',
}, params, true) file,
},
params,
true
)
assertTypeIs('createStickerSet', media, 'inputMediaDocument') assertTypeIs('createStickerSet', media, 'inputMediaDocument')
assertTypeIs('createStickerSet', media.id, 'inputDocument') assertTypeIs('createStickerSet', media.id, 'inputDocument')

View file

@ -24,7 +24,7 @@ const debug = require('debug')('mtcute:upload')
const OVERRIDE_MIME: Record<string, string> = { const OVERRIDE_MIME: Record<string, string> = {
// tg doesn't interpret `audio/opus` files as voice messages for some reason // tg doesn't interpret `audio/opus` files as voice messages for some reason
'audio/opus': 'audio/ogg' 'audio/opus': 'audio/ogg',
} }
/** /**

View file

@ -36,7 +36,7 @@ export async function createInviteLink(
_: 'messages.exportChatInvite', _: 'messages.exportChatInvite',
peer: await this.resolvePeer(chatId), peer: await this.resolvePeer(chatId),
expireDate: normalizeDate(params.expires), expireDate: normalizeDate(params.expires),
usageLimit: params.usageLimit usageLimit: params.usageLimit,
}) })
return new ChatInviteLink(this, res) return new ChatInviteLink(this, res)

View file

@ -40,7 +40,7 @@ export async function editInviteLink(
peer: await this.resolvePeer(chatId), peer: await this.resolvePeer(chatId),
link, link,
expireDate: normalizeDate(params.expires), expireDate: normalizeDate(params.expires),
usageLimit: params.usageLimit usageLimit: params.usageLimit,
}) })
const { users } = createUsersChatsIndex(res) const { users } = createUsersChatsIndex(res)

View file

@ -18,7 +18,7 @@ export async function exportInviteLink(
const res = await this.call({ const res = await this.call({
_: 'messages.exportChatInvite', _: 'messages.exportChatInvite',
peer: await this.resolvePeer(chatId), peer: await this.resolvePeer(chatId),
legacyRevokePermanent: true legacyRevokePermanent: true,
}) })
return new ChatInviteLink(this, res) return new ChatInviteLink(this, res)

View file

@ -27,14 +27,16 @@ export async function* getInviteLinkMembers(
for (;;) { for (;;) {
// for some reason ts needs annotation, idk // for some reason ts needs annotation, idk
const res: tl.RpcCallReturn['messages.getChatInviteImporters'] = await this.call({ const res: tl.RpcCallReturn['messages.getChatInviteImporters'] = await this.call(
_: 'messages.getChatInviteImporters', {
limit: Math.min(100, limit - current), _: 'messages.getChatInviteImporters',
peer, limit: Math.min(100, limit - current),
link, peer,
offsetDate, link,
offsetUser, offsetDate,
}) offsetUser,
}
)
if (!res.importers.length) break if (!res.importers.length) break
@ -45,7 +47,7 @@ export async function* getInviteLinkMembers(
offsetUser = { offsetUser = {
_: 'inputUser', _: 'inputUser',
userId: last.userId, userId: last.userId,
accessHash: (users[last.userId] as tl.RawUser).accessHash! accessHash: (users[last.userId] as tl.RawUser).accessHash!,
} }
for (const it of res.importers) { for (const it of res.importers) {

View file

@ -17,7 +17,7 @@ export async function getInviteLink(
const res = await this.call({ const res = await this.call({
_: 'messages.getExportedChatInvite', _: 'messages.getExportedChatInvite',
peer: await this.resolvePeer(chatId), peer: await this.resolvePeer(chatId),
link link,
}) })
const { users } = createUsersChatsIndex(res) const { users } = createUsersChatsIndex(res)

View file

@ -22,12 +22,15 @@ export async function revokeInviteLink(
_: 'messages.editExportedChatInvite', _: 'messages.editExportedChatInvite',
peer: await this.resolvePeer(chatId), peer: await this.resolvePeer(chatId),
link, link,
revoked: true revoked: true,
}) })
const { users } = createUsersChatsIndex(res) const { users } = createUsersChatsIndex(res)
const invite = res._ === 'messages.exportedChatInviteReplaced' ? res.newInvite : res.invite const invite =
res._ === 'messages.exportedChatInviteReplaced'
? res.newInvite
: res.invite
return new ChatInviteLink(this, invite, users) return new ChatInviteLink(this, invite, users)
} }

View file

@ -16,14 +16,13 @@ export function _findMessageInUpdate(
for (const u of res.updates) { for (const u of res.updates) {
if ( if (
isEdit && ( (isEdit &&
u._ === 'updateEditMessage' || (u._ === 'updateEditMessage' ||
u._ === 'updateEditChannelMessage' u._ === 'updateEditChannelMessage')) ||
) || !isEdit && ( (!isEdit &&
u._ === 'updateNewMessage' || (u._ === 'updateNewMessage' ||
u._ === 'updateNewChannelMessage' || u._ === 'updateNewChannelMessage' ||
u._ === 'updateNewScheduledMessage' u._ === 'updateNewScheduledMessage'))
)
) { ) {
const { users, chats } = createUsersChatsIndex(res) const { users, chats } = createUsersChatsIndex(res)

View file

@ -8,9 +8,7 @@ import {
} from '../../types' } from '../../types'
import { MaybeArray } from '@mtcute/core' import { MaybeArray } from '@mtcute/core'
import { tl } from '@mtcute/tl' import { tl } from '@mtcute/tl'
import { import { createUsersChatsIndex } from '../../utils/peer-utils'
createUsersChatsIndex,
} from '../../utils/peer-utils'
import { normalizeDate, randomUlong } from '../../utils/misc-utils' import { normalizeDate, randomUlong } from '../../utils/misc-utils'
import { assertIsUpdatesGroup } from '../../utils/updates-utils' import { assertIsUpdatesGroup } from '../../utils/updates-utils'

View file

@ -29,8 +29,8 @@ export async function _getDiscussionMessage(
{ {
_: 'inputPeerChannel', _: 'inputPeerChannel',
channelId: chat.id, channelId: chat.id,
accessHash: chat.accessHash! accessHash: chat.accessHash!,
}, },
msg.id msg.id,
] ]
} }

View file

@ -1,6 +1,6 @@
import { TelegramClient } from '../../client' import { TelegramClient } from '../../client'
import { InputPeerLike, Message, MtCuteTypeAssertionError } from '../../types' import { InputPeerLike, Message, MtCuteTypeAssertionError } from '../../types'
import { createUsersChatsIndex, } from '../../utils/peer-utils' import { createUsersChatsIndex } from '../../utils/peer-utils'
import { normalizeDate } from '../../utils/misc-utils' import { normalizeDate } from '../../utils/misc-utils'
/** /**

View file

@ -24,8 +24,7 @@ export async function getMessageGroup(
const messages = await this.getMessages(chatId, ids) const messages = await this.getMessages(chatId, ids)
const groupedId = messages.find((it) => it.id === message)!.groupedId const groupedId = messages.find((it) => it.id === message)!.groupedId
if (!groupedId) if (!groupedId) throw new MtCuteArgumentError('This message is not grouped')
throw new MtCuteArgumentError('This message is not grouped')
return messages.filter((it) => it.groupedId?.eq(groupedId)) return messages.filter((it) => it.groupedId?.eq(groupedId))
} }

View file

@ -27,7 +27,7 @@ export async function _normalizeInline(
if (!(id.dcId in this._connectionsForInline)) { if (!(id.dcId in this._connectionsForInline)) {
this._connectionsForInline[ this._connectionsForInline[
id.dcId id.dcId
] = await this.createAdditionalConnection(id.dcId) ] = await this.createAdditionalConnection(id.dcId)
} }
connection = this._connectionsForInline[id.dcId] connection = this._connectionsForInline[id.dcId]
} }

View file

@ -21,8 +21,7 @@ export async function _parseEntities(
} }
// either explicitly disabled or no available parser // either explicitly disabled or no available parser
if (!mode) return [text, []] if (!mode) return [text, []]
;[text, entities] = await this._parseModes[mode].parse(text)
;([text, entities] = await this._parseModes[mode].parse(text))
} }
// replace mentionName entities with input ones // replace mentionName entities with input ones

View file

@ -25,7 +25,7 @@ export async function pinMessage(
peer: await this.resolvePeer(chatId), peer: await this.resolvePeer(chatId),
id: messageId, id: messageId,
silent: !notify, silent: !notify,
pmOneside: !bothSides pmOneside: !bothSides,
}) })
this._handleUpdate(res) this._handleUpdate(res)

View file

@ -6,7 +6,11 @@ import {
Message, Message,
ReplyMarkup, ReplyMarkup,
} from '../../types' } from '../../types'
import { normalizeDate, normalizeMessageId, randomUlong } from '../../utils/misc-utils' import {
normalizeDate,
normalizeMessageId,
randomUlong,
} from '../../utils/misc-utils'
import { tl } from '@mtcute/tl' import { tl } from '@mtcute/tl'
import { assertIsUpdatesGroup } from '../../utils/updates-utils' import { assertIsUpdatesGroup } from '../../utils/updates-utils'
import { createUsersChatsIndex } from '../../utils/peer-utils' import { createUsersChatsIndex } from '../../utils/peer-utils'
@ -95,7 +99,10 @@ export async function sendMediaGroup(
let replyTo = normalizeMessageId(params.replyTo) let replyTo = normalizeMessageId(params.replyTo)
if (params.commentTo) { if (params.commentTo) {
;[peer, replyTo] = await this._getDiscussionMessage(peer, normalizeMessageId(params.commentTo)!) ;[peer, replyTo] = await this._getDiscussionMessage(
peer,
normalizeMessageId(params.commentTo)!
)
} }
const multiMedia: tl.RawInputSingleMedia[] = [] const multiMedia: tl.RawInputSingleMedia[] = []

View file

@ -6,7 +6,11 @@ import {
Message, Message,
ReplyMarkup, ReplyMarkup,
} from '../../types' } from '../../types'
import { normalizeDate, normalizeMessageId, randomUlong } from '../../utils/misc-utils' import {
normalizeDate,
normalizeMessageId,
randomUlong,
} from '../../utils/misc-utils'
/** /**
* Send a single media (a photo or a document-based media) * Send a single media (a photo or a document-based media)
@ -108,7 +112,10 @@ export async function sendMedia(
let replyTo = normalizeMessageId(params.replyTo) let replyTo = normalizeMessageId(params.replyTo)
if (params.commentTo) { if (params.commentTo) {
;[peer, replyTo] = await this._getDiscussionMessage(peer, normalizeMessageId(params.commentTo)!) ;[peer, replyTo] = await this._getDiscussionMessage(
peer,
normalizeMessageId(params.commentTo)!
)
} }
const res = await this.call({ const res = await this.call({

View file

@ -1,7 +1,11 @@
import { TelegramClient } from '../../client' import { TelegramClient } from '../../client'
import { tl } from '@mtcute/tl' import { tl } from '@mtcute/tl'
import { inputPeerToPeer } from '../../utils/peer-utils' import { inputPeerToPeer } from '../../utils/peer-utils'
import { normalizeDate, normalizeMessageId, randomUlong } from '../../utils/misc-utils' import {
normalizeDate,
normalizeMessageId,
randomUlong,
} from '../../utils/misc-utils'
import { InputPeerLike, Message, BotKeyboard, ReplyMarkup } from '../../types' import { InputPeerLike, Message, BotKeyboard, ReplyMarkup } from '../../types'
/** /**
@ -91,7 +95,10 @@ export async function sendText(
let replyTo = normalizeMessageId(params.replyTo) let replyTo = normalizeMessageId(params.replyTo)
if (params.commentTo) { if (params.commentTo) {
;[peer, replyTo] = await this._getDiscussionMessage(peer, normalizeMessageId(params.commentTo)!) ;[peer, replyTo] = await this._getDiscussionMessage(
peer,
normalizeMessageId(params.commentTo)!
)
} }
const res = await this.call({ const res = await this.call({

View file

@ -36,49 +36,49 @@ export async function sendTyping(
switch (status) { switch (status) {
case 'typing': case 'typing':
status = { _: 'sendMessageTypingAction' } status = { _: 'sendMessageTypingAction' }
break; break
case 'cancel': case 'cancel':
status = { _: 'sendMessageCancelAction' } status = { _: 'sendMessageCancelAction' }
break; break
case 'record_video': case 'record_video':
status = { _: 'sendMessageRecordVideoAction' } status = { _: 'sendMessageRecordVideoAction' }
break; break
case 'upload_video': case 'upload_video':
status = { _: 'sendMessageUploadVideoAction', progress } status = { _: 'sendMessageUploadVideoAction', progress }
break; break
case 'record_voice': case 'record_voice':
status = { _: 'sendMessageRecordAudioAction' } status = { _: 'sendMessageRecordAudioAction' }
break; break
case 'upload_voice': case 'upload_voice':
status = { _: 'sendMessageUploadAudioAction', progress } status = { _: 'sendMessageUploadAudioAction', progress }
break; break
case 'upload_photo': case 'upload_photo':
status = { _: 'sendMessageUploadPhotoAction', progress } status = { _: 'sendMessageUploadPhotoAction', progress }
break; break
case 'upload_document': case 'upload_document':
status = { _: 'sendMessageUploadDocumentAction', progress } status = { _: 'sendMessageUploadDocumentAction', progress }
break; break
case 'geo': case 'geo':
status = { _: 'sendMessageGeoLocationAction' } status = { _: 'sendMessageGeoLocationAction' }
break; break
case 'contact': case 'contact':
status = { _: 'sendMessageChooseContactAction' } status = { _: 'sendMessageChooseContactAction' }
break; break
case 'game': case 'game':
status = { _: 'sendMessageGamePlayAction' } status = { _: 'sendMessageGamePlayAction' }
break; break
case 'record_round': case 'record_round':
status = { _: 'sendMessageRecordRoundAction' } status = { _: 'sendMessageRecordRoundAction' }
break; break
case 'upload_round': case 'upload_round':
status = { _: 'sendMessageUploadRoundAction', progress } status = { _: 'sendMessageUploadRoundAction', progress }
break; break
case 'speak_call': case 'speak_call':
status = { _: 'speakingInGroupCallAction' } status = { _: 'speakingInGroupCallAction' }
break; break
case 'history_import': case 'history_import':
status = { _: 'sendMessageHistoryImportAction', progress } status = { _: 'sendMessageHistoryImportAction', progress }
break; break
} }
} }
@ -86,6 +86,6 @@ export async function sendTyping(
_: 'messages.setTyping', _: 'messages.setTyping',
peer: await this.resolvePeer(chatId), peer: await this.resolvePeer(chatId),
action: status, action: status,
topMsgId: params?.threadId topMsgId: params?.threadId,
}) })
} }

View file

@ -17,11 +17,13 @@ export async function unpinAllMessages(
const res = await this.call({ const res = await this.call({
_: 'messages.unpinAllMessages', _: 'messages.unpinAllMessages',
peer peer,
}) })
if (isInputPeerChannel(peer)) { if (isInputPeerChannel(peer)) {
this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount, peer.channelId)) this._handleUpdate(
createDummyUpdate(res.pts, res.ptsCount, peer.channelId)
)
} else { } else {
this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount)) this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount))
} }

View file

@ -14,13 +14,13 @@ import { InputPeerLike } from '../../types'
export async function unpinMessage( export async function unpinMessage(
this: TelegramClient, this: TelegramClient,
chatId: InputPeerLike, chatId: InputPeerLike,
messageId: number, messageId: number
): Promise<void> { ): Promise<void> {
const res = await this.call({ const res = await this.call({
_: 'messages.updatePinnedMessage', _: 'messages.updatePinnedMessage',
peer: await this.resolvePeer(chatId), peer: await this.resolvePeer(chatId),
id: messageId, id: messageId,
unpin: true unpin: true,
}) })
this._handleUpdate(res) this._handleUpdate(res)

View file

@ -12,8 +12,11 @@ export async function initTakeoutSession(
this: TelegramClient, this: TelegramClient,
params: Omit<tl.account.RawInitTakeoutSessionRequest, '_'> params: Omit<tl.account.RawInitTakeoutSessionRequest, '_'>
): Promise<TakeoutSession> { ): Promise<TakeoutSession> {
return new TakeoutSession(this, await this.call({ return new TakeoutSession(
_: 'account.initTakeoutSession', this,
...params await this.call({
})) _: 'account.initTakeoutSession',
...params,
})
)
} }

View file

@ -29,7 +29,11 @@ export async function changeCloudPassword(
) )
const oldSrp = await computeSrpParams(this._crypto, pwd, currentPassword) const oldSrp = await computeSrpParams(this._crypto, pwd, currentPassword)
const newHash = await computeNewPasswordHash(this._crypto, algo, newPassword) const newHash = await computeNewPasswordHash(
this._crypto,
algo,
newPassword
)
await this.call({ await this.call({
_: 'account.updatePasswordSettings', _: 'account.updatePasswordSettings',
@ -38,7 +42,7 @@ export async function changeCloudPassword(
_: 'account.passwordInputSettings', _: 'account.passwordInputSettings',
newAlgo: algo, newAlgo: algo,
newPasswordHash: newHash, newPasswordHash: newHash,
hint hint,
} },
}) })
} }

View file

@ -43,7 +43,7 @@ export async function enableCloudPassword(
newAlgo: algo, newAlgo: algo,
newPasswordHash: newHash, newPasswordHash: newHash,
hint, hint,
email email,
} },
}) })
} }

View file

@ -12,7 +12,7 @@ export async function verifyPasswordEmail(
): Promise<void> { ): Promise<void> {
await this.call({ await this.call({
_: 'account.confirmPasswordEmail', _: 'account.confirmPasswordEmail',
code code,
}) })
} }
@ -23,7 +23,7 @@ export async function verifyPasswordEmail(
*/ */
export async function resendPasswordEmail(this: TelegramClient): Promise<void> { export async function resendPasswordEmail(this: TelegramClient): Promise<void> {
await this.call({ await this.call({
_: 'account.resendPasswordEmail' _: 'account.resendPasswordEmail',
}) })
} }
@ -34,6 +34,6 @@ export async function resendPasswordEmail(this: TelegramClient): Promise<void> {
*/ */
export async function cancelPasswordEmail(this: TelegramClient): Promise<void> { export async function cancelPasswordEmail(this: TelegramClient): Promise<void> {
await this.call({ await this.call({
_: 'account.cancelPasswordEmail' _: 'account.cancelPasswordEmail',
}) })
} }

View file

@ -10,7 +10,7 @@ import { computeSrpParams } from '@mtcute/core'
*/ */
export async function removeCloudPassword( export async function removeCloudPassword(
this: TelegramClient, this: TelegramClient,
password: string, password: string
): Promise<void> { ): Promise<void> {
const pwd = await this.call({ _: 'account.getPassword' }) const pwd = await this.call({ _: 'account.getPassword' })
if (!pwd.hasPassword) if (!pwd.hasPassword)
@ -25,7 +25,7 @@ export async function removeCloudPassword(
_: 'account.passwordInputSettings', _: 'account.passwordInputSettings',
newAlgo: { _: 'passwordKdfAlgoUnknown' }, newAlgo: { _: 'passwordKdfAlgoUnknown' },
newPasswordHash: Buffer.alloc(0), newPasswordHash: Buffer.alloc(0),
hint: '' hint: '',
} },
}) })
} }

View file

@ -33,12 +33,12 @@ export async function addStickerToSet(
* @param total Total file size * @param total Total file size
*/ */
progressCallback?: (uploaded: number, total: number) => void progressCallback?: (uploaded: number, total: number) => void
}, }
): Promise<StickerSet> { ): Promise<StickerSet> {
if (typeof id === 'string') { if (typeof id === 'string') {
id = { id = {
_: 'inputStickerSetShortName', _: 'inputStickerSetShortName',
shortName: id shortName: id,
} }
} }
@ -47,18 +47,21 @@ export async function addStickerToSet(
stickerset: id, stickerset: id,
sticker: { sticker: {
_: 'inputStickerSetItem', _: 'inputStickerSetItem',
document: await this._normalizeFileToDocument(sticker.file, params ?? {}), document: await this._normalizeFileToDocument(
sticker.file,
params ?? {}
),
emoji: sticker.emojis, emoji: sticker.emojis,
maskCoords: sticker.maskPosition maskCoords: sticker.maskPosition
? { ? {
_: 'maskCoords', _: 'maskCoords',
n: MASK_POS[sticker.maskPosition.point], n: MASK_POS[sticker.maskPosition.point],
x: sticker.maskPosition.x, x: sticker.maskPosition.x,
y: sticker.maskPosition.y, y: sticker.maskPosition.y,
zoom: sticker.maskPosition.scale, zoom: sticker.maskPosition.scale,
} }
: undefined, : undefined,
} },
}) })
return new StickerSet(this, res) return new StickerSet(this, res)

View file

@ -25,7 +25,7 @@ export async function deleteStickerFromSet(
const res = await this.call({ const res = await this.call({
_: 'stickers.removeStickerFromSet', _: 'stickers.removeStickerFromSet',
sticker sticker,
}) })
return new StickerSet(this, res) return new StickerSet(this, res)

View file

@ -17,7 +17,7 @@ export async function getInstalledStickers(
): Promise<StickerSet[]> { ): Promise<StickerSet[]> {
const res = await this.call({ const res = await this.call({
_: 'messages.getAllStickers', _: 'messages.getAllStickers',
hash: 0 hash: 0,
}) })
assertTypeIs('getInstalledStickers', res, 'messages.allStickers') assertTypeIs('getInstalledStickers', res, 'messages.allStickers')

View file

@ -14,16 +14,19 @@ export async function getStickerSet(
): Promise<StickerSet> { ): Promise<StickerSet> {
let input: tl.TypeInputStickerSet let input: tl.TypeInputStickerSet
if (typeof id === 'string') { if (typeof id === 'string') {
input = id === 'emoji' ? { input =
_: 'inputStickerSetAnimatedEmoji' id === 'emoji'
} : { ? {
_: 'inputStickerSetShortName', _: 'inputStickerSetAnimatedEmoji',
shortName: id }
} : {
_: 'inputStickerSetShortName',
shortName: id,
}
} else if ('dice' in id) { } else if ('dice' in id) {
input = { input = {
_: 'inputStickerSetDice', _: 'inputStickerSetDice',
emoticon: id.dice emoticon: id.dice,
} }
} else { } else {
input = id input = id
@ -31,7 +34,7 @@ export async function getStickerSet(
const res = await this.call({ const res = await this.call({
_: 'messages.getStickerSet', _: 'messages.getStickerSet',
stickerset: input stickerset: input,
}) })
return new StickerSet(this, res) return new StickerSet(this, res)

View file

@ -30,7 +30,7 @@ export async function moveStickerInSet(
const res = await this.call({ const res = await this.call({
_: 'stickers.changeStickerPosition', _: 'stickers.changeStickerPosition',
sticker, sticker,
position position,
}) })
return new StickerSet(this, res) return new StickerSet(this, res)

View file

@ -23,19 +23,19 @@ export async function setStickerSetThumb(
* @param total Total file size * @param total Total file size
*/ */
progressCallback?: (uploaded: number, total: number) => void progressCallback?: (uploaded: number, total: number) => void
}, }
): Promise<StickerSet> { ): Promise<StickerSet> {
if (typeof id === 'string') { if (typeof id === 'string') {
id = { id = {
_: 'inputStickerSetShortName', _: 'inputStickerSetShortName',
shortName: id shortName: id,
} }
} }
const res = await this.call({ const res = await this.call({
_: 'stickers.setStickerSetThumb', _: 'stickers.setStickerSetThumb',
stickerset: id, stickerset: id,
thumb: await this._normalizeFileToDocument(thumb, params ?? {}) thumb: await this._normalizeFileToDocument(thumb, params ?? {}),
}) })
return new StickerSet(this, res) return new StickerSet(this, res)

View file

@ -106,7 +106,10 @@ export async function _loadStorage(this: TelegramClient): Promise<void> {
/** /**
* @internal * @internal
*/ */
export async function _saveStorage(this: TelegramClient, afterImport = false): Promise<void> { export async function _saveStorage(
this: TelegramClient,
afterImport = false
): Promise<void> {
// save updates state to the session // save updates state to the session
if (afterImport) { if (afterImport) {
@ -312,7 +315,10 @@ async function _fetchPeersForShort(
case 'updateNewChannelMessage': case 'updateNewChannelMessage':
case 'updateEditMessage': case 'updateEditMessage':
case 'updateEditChannelMessage': { case 'updateEditChannelMessage': {
const msg = upd._ === 'message' || upd._ === 'messageService' ? upd : upd.message const msg =
upd._ === 'message' || upd._ === 'messageService'
? upd
: upd.message
if (msg._ === 'messageEmpty') return null if (msg._ === 'messageEmpty') return null
// ref: https://github.com/tdlib/td/blob/e1ebf743988edfcf4400cd5d33a664ff941dc13e/td/telegram/UpdatesManager.cpp#L412 // ref: https://github.com/tdlib/td/blob/e1ebf743988edfcf4400cd5d33a664ff941dc13e/td/telegram/UpdatesManager.cpp#L412
@ -357,13 +363,19 @@ async function _fetchPeersForShort(
} }
break break
case 'messageActionChatJoinedByLink': case 'messageActionChatJoinedByLink':
if (!(await fetchPeer(msg.action.inviterId))) return null if (!(await fetchPeer(msg.action.inviterId)))
return null
break break
case 'messageActionChatDeleteUser': case 'messageActionChatDeleteUser':
if (!(await fetchPeer(msg.action.userId))) return null if (!(await fetchPeer(msg.action.userId))) return null
break break
case 'messageActionChatMigrateTo': case 'messageActionChatMigrateTo':
if (!(await fetchPeer(MAX_CHANNEL_ID - msg.action.channelId))) return null if (
!(await fetchPeer(
MAX_CHANNEL_ID - msg.action.channelId
))
)
return null
break break
case 'messageActionChannelMigrateFrom': case 'messageActionChannelMigrateFrom':
if (!(await fetchPeer(-msg.action.chatId))) return null if (!(await fetchPeer(-msg.action.chatId))) return null
@ -465,7 +477,12 @@ async function _loadDifference(
if (nextLocalPts) { if (nextLocalPts) {
if (nextLocalPts > pts) continue if (nextLocalPts > pts) continue
if (nextLocalPts < pts) { if (nextLocalPts < pts) {
await _loadChannelDifference.call(this, cid, noDispatch, pts) await _loadChannelDifference.call(
this,
cid,
noDispatch,
pts
)
continue continue
} }
} }
@ -735,7 +752,10 @@ export function _handleUpdate(
this._config = await this.call({ _: 'help.getConfig' }) this._config = await this.call({ _: 'help.getConfig' })
} else { } else {
if (!noDispatch) { if (!noDispatch) {
const peers = await _fetchPeersForShort.call(this, upd) const peers = await _fetchPeersForShort.call(
this,
upd
)
if (!peers) { if (!peers) {
// some peer is not cached. // some peer is not cached.
// need to re-fetch the thing, and cache them on the way // need to re-fetch the thing, and cache them on the way

View file

@ -25,6 +25,6 @@ export async function deleteProfilePhotos(
await this.call({ await this.call({
_: 'photos.deletePhotos', _: 'photos.deletePhotos',
id: photos id: photos,
}) })
} }

View file

@ -40,7 +40,7 @@ export async function getProfilePhotos(
userId: peer, userId: peer,
offset: params.offset ?? 0, offset: params.offset ?? 0,
limit: params.limit ?? 100, limit: params.limit ?? 100,
maxId: bigInt.zero maxId: bigInt.zero,
}) })
return res.photos.map((it) => new Photo(this, it as tl.RawPhoto)) return res.photos.map((it) => new Photo(this, it as tl.RawPhoto))

View file

@ -62,7 +62,7 @@ export async function* iterProfilePhotos(
userId: peer, userId: peer,
limit: Math.min(limit, total - current), limit: Math.min(limit, total - current),
offset, offset,
maxId maxId,
}) })
if (!res.photos.length) break if (!res.photos.length) break

View file

@ -19,9 +19,7 @@ export async function resolvePeerMany<
>( >(
this: TelegramClient, this: TelegramClient,
peerIds: InputPeerLike[], peerIds: InputPeerLike[],
normalizer: ( normalizer: (obj: tl.TypeInputPeer) => T | null
obj: tl.TypeInputPeer
) => T | null
): Promise<T[]> ): Promise<T[]>
/** /**

View file

@ -75,7 +75,10 @@ export async function resolvePeer(
accessHash: found.accessHash!, accessHash: found.accessHash!,
} }
} else { } else {
const id = res.peer._ === 'peerChannel' ? res.peer.channelId : res.peer.chatId const id =
res.peer._ === 'peerChannel'
? res.peer.channelId
: res.peer.chatId
const found = res.chats.find((it) => it.id === id) const found = res.chats.find((it) => it.id === id)
if (found) if (found)
@ -85,13 +88,13 @@ export async function resolvePeer(
return { return {
_: 'inputPeerChannel', _: 'inputPeerChannel',
channelId: found.id, channelId: found.id,
accessHash: found.accessHash! accessHash: found.accessHash!,
} }
case 'chat': case 'chat':
case 'chatForbidden': case 'chatForbidden':
return { return {
_: 'inputPeerChat', _: 'inputPeerChat',
chatId: found.id chatId: found.id,
} }
} }
} }
@ -145,7 +148,7 @@ export async function resolvePeer(
return { return {
_: 'inputPeerChat', _: 'inputPeerChat',
chatId: -peerId chatId: -peerId,
} }
// break // break
} }
@ -163,7 +166,10 @@ export async function resolvePeer(
}) })
const found = res.chats.find((it) => it.id === id) const found = res.chats.find((it) => it.id === id)
if (found && (found._ === 'channel' || found._ === 'channelForbidden')) if (
found &&
(found._ === 'channel' || found._ === 'channelForbidden')
)
return { return {
_: 'inputPeerChannel', _: 'inputPeerChannel',
channelId: found.id, channelId: found.id,

View file

@ -12,6 +12,6 @@ export async function setOffline(
): Promise<void> { ): Promise<void> {
await this.call({ await this.call({
_: 'account.updateStatus', _: 'account.updateStatus',
offline offline,
}) })
} }

View file

@ -20,8 +20,11 @@ export async function setProfilePhoto(
): Promise<Photo> { ): Promise<Photo> {
const res = await this.call({ const res = await this.call({
_: 'photos.uploadProfilePhoto', _: 'photos.uploadProfilePhoto',
[type === 'photo' ? 'file' : 'video']: await this._normalizeInputFile(media, {}), [type === 'photo' ? 'file' : 'video']: await this._normalizeInputFile(
videoStartTs: previewSec media,
{}
),
videoStartTs: previewSec,
}) })
return new Photo(this, res.photo as tl.RawPhoto) return new Photo(this, res.photo as tl.RawPhoto)

View file

@ -32,7 +32,7 @@ export async function updateProfile(
_: 'account.updateProfile', _: 'account.updateProfile',
firstName: params.firstName, firstName: params.firstName,
lastName: params.lastName, lastName: params.lastName,
about: params.bio about: params.bio,
}) })
return new User(this, res) return new User(this, res)

View file

@ -18,7 +18,7 @@ export async function updateUsername(
const res = await this.call({ const res = await this.call({
_: 'account.updateUsername', _: 'account.updateUsername',
username username,
}) })
return new User(this, res) return new User(this, res)

View file

@ -12,7 +12,11 @@ export class GameHighScore {
readonly _users: UsersIndex readonly _users: UsersIndex
constructor (client: TelegramClient, raw: tl.RawHighScore, users: UsersIndex) { constructor(
client: TelegramClient,
raw: tl.RawHighScore,
users: UsersIndex
) {
this.client = client this.client = client
this.raw = raw this.raw = raw
this._users = users this._users = users

View file

@ -160,7 +160,10 @@ export namespace BotInlineMessage {
export function geo( export function geo(
latitude: number, latitude: number,
longitude: number, longitude: number,
params: Omit<InputInlineMessageGeo, 'type' | 'latitude' | 'longitude'> = {} params: Omit<
InputInlineMessageGeo,
'type' | 'latitude' | 'longitude'
> = {}
): InputInlineMessageGeo { ): InputInlineMessageGeo {
const ret = params as tl.Mutable<InputInlineMessageGeo> const ret = params as tl.Mutable<InputInlineMessageGeo>
ret.type = 'geo' ret.type = 'geo'

View file

@ -1,5 +1,5 @@
import { tl } from '@mtcute/tl' import { tl } from '@mtcute/tl'
import { BotInlineMessage, InputInlineMessage, InputInlineMessageGame } from './input-inline-message' import { BotInlineMessage, InputInlineMessage } from './input-inline-message'
import { TelegramClient } from '../../../client' import { TelegramClient } from '../../../client'
import { fileIdToInputDocument, fileIdToInputPhoto } from '@mtcute/file-id' import { fileIdToInputDocument, fileIdToInputPhoto } from '@mtcute/file-id'
import { extractFileName } from '../../../utils/file-utils' import { extractFileName } from '../../../utils/file-utils'
@ -711,7 +711,12 @@ export namespace BotInline {
obj: InputInlineResult, obj: InputInlineResult,
fallback?: string fallback?: string
): tl.RawInputWebDocument | undefined => { ): tl.RawInputWebDocument | undefined => {
if (obj.type !== 'voice' && obj.type !== 'audio' && obj.type !== 'sticker' && obj.type !== 'game') { if (
obj.type !== 'voice' &&
obj.type !== 'audio' &&
obj.type !== 'sticker' &&
obj.type !== 'game'
) {
if (!obj.thumb || typeof obj.thumb === 'string') { if (!obj.thumb || typeof obj.thumb === 'string') {
if (!obj.thumb && !fallback) { if (!obj.thumb && !fallback) {
return undefined return undefined
@ -805,11 +810,13 @@ export namespace BotInline {
parseMode parseMode
) )
if (sendMessage._ !== 'inputBotInlineMessageGame') { if (sendMessage._ !== 'inputBotInlineMessageGame') {
throw new MtCuteArgumentError('game inline result must contain a game inline message') throw new MtCuteArgumentError(
'game inline result must contain a game inline message'
)
} }
} else { } else {
sendMessage = { sendMessage = {
_: 'inputBotInlineMessageGame' _: 'inputBotInlineMessageGame',
} }
} }
@ -817,7 +824,7 @@ export namespace BotInline {
_: 'inputBotInlineResultGame', _: 'inputBotInlineResultGame',
id: obj.id, id: obj.id,
shortName: obj.shortName, shortName: obj.shortName,
sendMessage sendMessage,
} }
} }
@ -830,7 +837,9 @@ export namespace BotInline {
) )
} else { } else {
if (obj.type === 'venue') if (obj.type === 'venue')
throw new MtCuteArgumentError('message bust be supplied for venue inline result') throw new MtCuteArgumentError(
'message bust be supplied for venue inline result'
)
if ( if (
obj.type === 'video' && obj.type === 'video' &&
@ -856,8 +865,7 @@ export namespace BotInline {
phoneNumber: obj.phone, phoneNumber: obj.phone,
firstName: obj.firstName, firstName: obj.firstName,
lastName: obj.lastName ?? '', lastName: obj.lastName ?? '',
vcard: '' vcard: '',
} }
} else { } else {
sendMessage = { sendMessage = {
@ -872,12 +880,18 @@ export namespace BotInline {
| tl.TypeInputDocument | tl.TypeInputDocument
| tl.TypeInputPhoto | tl.TypeInputPhoto
| undefined = undefined | undefined = undefined
if (obj.type !== 'geo' && obj.type !== 'venue' && obj.type !== 'contact') { if (
obj.type !== 'geo' &&
obj.type !== 'venue' &&
obj.type !== 'contact'
) {
if (typeof obj.media === 'string') { if (typeof obj.media === 'string') {
// file id or url // file id or url
if (obj.media.match(/^https?:\/\//)) { if (obj.media.match(/^https?:\/\//)) {
if (obj.type === 'sticker') if (obj.type === 'sticker')
throw new MtCuteArgumentError('sticker inline result cannot contain a URL') throw new MtCuteArgumentError(
'sticker inline result cannot contain a URL'
)
let mime: string let mime: string
if (obj.type === 'video') mime = 'video/mp4' if (obj.type === 'video') mime = 'video/mp4'
@ -959,7 +973,9 @@ export namespace BotInline {
// but whatever. // but whatever.
// ref: https://github.com/tdlib/td/blob/master/td/telegram/InlineQueriesManager.cpp // ref: https://github.com/tdlib/td/blob/master/td/telegram/InlineQueriesManager.cpp
if (obj.type === 'contact') { if (obj.type === 'contact') {
title = obj.lastName?.length ? `${obj.firstName} ${obj.lastName}` : obj.firstName title = obj.lastName?.length
? `${obj.firstName} ${obj.lastName}`
: obj.firstName
} else if (obj.type !== 'sticker') { } else if (obj.type !== 'sticker') {
title = obj.title title = obj.title
} }
@ -972,7 +988,11 @@ export namespace BotInline {
description = obj.address description = obj.address
} else if (obj.type === 'contact') { } else if (obj.type === 'contact') {
description = obj.phone description = obj.phone
} else if (obj.type !== 'gif' && obj.type !== 'voice' && obj.type !== 'sticker') { } else if (
obj.type !== 'gif' &&
obj.type !== 'voice' &&
obj.type !== 'sticker'
) {
description = obj.description description = obj.description
} }

View file

@ -302,10 +302,10 @@ export namespace BotKeyboard {
text, text,
url, url,
bot: params.bot ?? { bot: params.bot ?? {
_: 'inputUserSelf' _: 'inputUserSelf',
}, },
fwdText: params.fwdText, fwdText: params.fwdText,
requestWriteAccess: params.requestWriteAccess requestWriteAccess: params.requestWriteAccess,
} }
} }

View file

@ -29,7 +29,10 @@ export class FileLocation {
| tl.TypeInputFileLocation | tl.TypeInputFileLocation
| tl.TypeInputWebFileLocation | tl.TypeInputWebFileLocation
| Buffer | Buffer
| (() => tl.TypeInputFileLocation | tl.TypeInputWebFileLocation | Buffer) | (() =>
| tl.TypeInputFileLocation
| tl.TypeInputWebFileLocation
| Buffer)
/** /**
* File size in bytes, when available * File size in bytes, when available
@ -47,7 +50,10 @@ export class FileLocation {
| tl.TypeInputFileLocation | tl.TypeInputFileLocation
| tl.TypeInputWebFileLocation | tl.TypeInputWebFileLocation
| Buffer | Buffer
| (() => tl.TypeInputFileLocation | tl.TypeInputWebFileLocation | Buffer), | (() =>
| tl.TypeInputFileLocation
| tl.TypeInputWebFileLocation
| Buffer),
fileSize?: number, fileSize?: number,
dcId?: number dcId?: number
) { ) {

View file

@ -25,7 +25,7 @@ export interface UploadedFile {
} }
/** @internal */ /** @internal */
export function isUploadedFile(obj: any): obj is UploadedFile { export function isUploadedFile(obj: object): obj is UploadedFile {
return ( return (
obj && obj &&
typeof obj === 'object' && typeof obj === 'object' &&

View file

@ -52,7 +52,11 @@ export interface FileDownloadParameters {
* File location which should be downloaded. * File location which should be downloaded.
* You can also provide TDLib and Bot API compatible File ID * You can also provide TDLib and Bot API compatible File ID
*/ */
location: tl.TypeInputFileLocation | tl.TypeInputWebFileLocation | FileLocation | string location:
| tl.TypeInputFileLocation
| tl.TypeInputWebFileLocation
| FileLocation
| string
/** /**
* Total file size, if known. * Total file size, if known.

View file

@ -171,7 +171,7 @@ export class Dice {
get inputMedia(): tl.TypeInputMedia { get inputMedia(): tl.TypeInputMedia {
return { return {
_: 'inputMediaDice', _: 'inputMediaDice',
emoticon: this.obj.emoticon emoticon: this.obj.emoticon,
} }
} }
} }

View file

@ -3,7 +3,6 @@ import { tl } from '@mtcute/tl'
import { Thumbnail } from './thumbnail' import { Thumbnail } from './thumbnail'
import { TelegramClient } from '../../client' import { TelegramClient } from '../../client'
import { makeInspectable } from '../utils' import { makeInspectable } from '../utils'
import { InputMediaLike } from './input-media'
import { tdFileId as td, toFileId, toUniqueFileId } from '@mtcute/file-id' import { tdFileId as td, toFileId, toUniqueFileId } from '@mtcute/file-id'
/** /**
@ -105,7 +104,7 @@ export class RawDocument extends FileLocation {
_: 'inputDocument', _: 'inputDocument',
id: this.doc.id, id: this.doc.id,
accessHash: this.doc.accessHash, accessHash: this.doc.accessHash,
fileReference: this.doc.fileReference fileReference: this.doc.fileReference,
} }
} }
@ -117,7 +116,7 @@ export class RawDocument extends FileLocation {
get inputMedia(): tl.TypeInputMedia { get inputMedia(): tl.TypeInputMedia {
return { return {
_: 'inputMediaDocument', _: 'inputMediaDocument',
id: this.inputDocument id: this.inputDocument,
} }
} }

View file

@ -91,8 +91,8 @@ export class Game {
id: { id: {
_: 'inputGameID', _: 'inputGameID',
id: this.game.id, id: this.game.id,
accessHash: this.game.accessHash accessHash: this.game.accessHash,
} },
} }
} }
} }

View file

@ -2,7 +2,6 @@ import { InputFileLike } from '../files'
import { tl } from '@mtcute/tl' import { tl } from '@mtcute/tl'
import { Venue } from './venue' import { Venue } from './venue'
import { MaybeArray } from '@mtcute/core' import { MaybeArray } from '@mtcute/core'
import { InputInlineResultGame } from '../bots'
interface BaseInputMedia { interface BaseInputMedia {
/** /**
@ -728,7 +727,10 @@ export namespace InputMedia {
export function geoLive( export function geoLive(
latitude: number, latitude: number,
longitude: number, longitude: number,
params: OmitTypeAndFile<InputMediaGeoLive, 'latitude' | 'longitude'> = {} params: OmitTypeAndFile<
InputMediaGeoLive,
'latitude' | 'longitude'
> = {}
): InputMediaGeoLive { ): InputMediaGeoLive {
const ret = params as tl.Mutable<InputMediaGeoLive> const ret = params as tl.Mutable<InputMediaGeoLive>
ret.type = 'geo_live' ret.type = 'geo_live'

View file

@ -11,7 +11,7 @@ export class Invoice {
readonly client: TelegramClient readonly client: TelegramClient
readonly raw: tl.RawMessageMediaInvoice readonly raw: tl.RawMessageMediaInvoice
constructor (client: TelegramClient, raw: tl.RawMessageMediaInvoice) { constructor(client: TelegramClient, raw: tl.RawMessageMediaInvoice) {
this.client = client this.client = client
this.raw = raw this.raw = raw
} }

View file

@ -40,42 +40,44 @@ export class Location {
* Create {@link FileLocation} containing * Create {@link FileLocation} containing
* server-generated image with the map preview * server-generated image with the map preview
*/ */
preview(params: { preview(
/** params: {
* Map width in pixels before applying scale (16-1024) /**
* * Map width in pixels before applying scale (16-1024)
* Defaults to `128` *
*/ * Defaults to `128`
width?: number */
width?: number
/** /**
* Map height in pixels before applying scale (16-1024) * Map height in pixels before applying scale (16-1024)
* *
* Defaults to `128` * Defaults to `128`
*/ */
height?: number height?: number
/** /**
* Map zoom level (13-20) * Map zoom level (13-20)
* *
* Defaults to `15` * Defaults to `15`
*/ */
zoom?: number zoom?: number
/** /**
* Map scale (1-3) * Map scale (1-3)
* *
* Defaults to `1` * Defaults to `1`
*/ */
scale?: number scale?: number
} = {}): FileLocation { } = {}
): FileLocation {
return new FileLocation(this.client, { return new FileLocation(this.client, {
_: 'inputWebFileGeoPointLocation', _: 'inputWebFileGeoPointLocation',
geoPoint: { geoPoint: {
_: 'inputGeoPoint', _: 'inputGeoPoint',
lat: this.geo.lat, lat: this.geo.lat,
long: this.geo.long, long: this.geo.long,
accuracyRadius: this.geo.accuracyRadius accuracyRadius: this.geo.accuracyRadius,
}, },
accessHash: this.geo.accessHash, accessHash: this.geo.accessHash,
w: params.width ?? 128, w: params.width ?? 128,
@ -97,8 +99,8 @@ export class Location {
_: 'inputGeoPoint', _: 'inputGeoPoint',
lat: this.geo.lat, lat: this.geo.lat,
long: this.geo.long, long: this.geo.long,
accuracyRadius: this.geo.accuracyRadius accuracyRadius: this.geo.accuracyRadius,
} },
} }
} }
} }
@ -141,11 +143,11 @@ export class LiveLocation extends Location {
_: 'inputGeoPoint', _: 'inputGeoPoint',
lat: this.geo.lat, lat: this.geo.lat,
long: this.geo.long, long: this.geo.long,
accuracyRadius: this.geo.accuracyRadius accuracyRadius: this.geo.accuracyRadius,
}, },
heading: this.live.heading, heading: this.live.heading,
period: this.live.period, period: this.live.period,
proximityNotificationRadius: this.live.proximityNotificationRadius proximityNotificationRadius: this.live.proximityNotificationRadius,
} }
} }

View file

@ -4,7 +4,6 @@ import { TelegramClient } from '../../client'
import { MtCuteArgumentError } from '../errors' import { MtCuteArgumentError } from '../errors'
import { Thumbnail } from './thumbnail' import { Thumbnail } from './thumbnail'
import { makeInspectable } from '../utils' import { makeInspectable } from '../utils'
import { InputMediaLike } from './input-media'
/** /**
* A photo * A photo

View file

@ -86,7 +86,7 @@ export class Poll {
data: ans.option, data: ans.option,
voters: res.voters, voters: res.voters,
chosen: !!res.chosen, chosen: !!res.chosen,
correct: !!res.correct correct: !!res.correct,
} }
} else { } else {
return { return {
@ -94,7 +94,7 @@ export class Poll {
data: ans.option, data: ans.option,
voters: 0, voters: 0,
chosen: false, chosen: false,
correct: false correct: false,
} }
} }
}) })
@ -210,7 +210,7 @@ export class Poll {
question: this.raw.question, question: this.raw.question,
answers: this.raw.answers, answers: this.raw.answers,
closePeriod: this.raw.closePeriod, closePeriod: this.raw.closePeriod,
closeDate: this.raw.closeDate closeDate: this.raw.closeDate,
}, },
} }
} }

View file

@ -125,7 +125,7 @@ export class Sticker extends RawDocument {
point: MASK_POS[raw.n], point: MASK_POS[raw.n],
x: raw.x, x: raw.x,
y: raw.y, y: raw.y,
scale: raw.zoom scale: raw.zoom,
} }
} }

View file

@ -3,7 +3,6 @@ import { Location } from './location'
import { assertTypeIs } from '../../utils/type-assertion' import { assertTypeIs } from '../../utils/type-assertion'
import { makeInspectable } from '../utils' import { makeInspectable } from '../utils'
import { TelegramClient } from '../../client' import { TelegramClient } from '../../client'
import bigInt from 'big-integer'
export namespace Venue { export namespace Venue {
export interface VenueSource { export interface VenueSource {
@ -33,7 +32,7 @@ export class Venue {
readonly client: TelegramClient readonly client: TelegramClient
readonly raw: tl.RawMessageMediaVenue readonly raw: tl.RawMessageMediaVenue
constructor (client: TelegramClient, raw: tl.RawMessageMediaVenue) { constructor(client: TelegramClient, raw: tl.RawMessageMediaVenue) {
this.client = client this.client = client
this.raw = raw this.raw = raw
} }
@ -106,7 +105,7 @@ export class Venue {
address: this.raw.address, address: this.raw.address,
provider: this.raw.provider, provider: this.raw.provider,
venueId: this.raw.venueId, venueId: this.raw.venueId,
venueType: this.raw.venueType venueType: this.raw.venueType,
} }
} }
} }

View file

@ -1,6 +1,9 @@
import { tl } from '@mtcute/tl' import { tl } from '@mtcute/tl'
import { Photo } from '../media' import { Photo } from '../media'
import { _callDiscardReasonFromTl, CallDiscardReason } from '../calls/discard-reason' import {
_callDiscardReasonFromTl,
CallDiscardReason,
} from '../calls/discard-reason'
import { Message } from './message' import { Message } from './message'
export namespace MessageAction { export namespace MessageAction {
@ -279,7 +282,10 @@ export type MessageAction =
| null | null
/** @internal */ /** @internal */
export function _messageActionFromTl(this: Message, act: tl.TypeMessageAction): MessageAction { export function _messageActionFromTl(
this: Message,
act: tl.TypeMessageAction
): MessageAction {
switch (act._) { switch (act._) {
case 'messageActionChatCreate': case 'messageActionChatCreate':
return { return {
@ -329,10 +335,7 @@ export function _messageActionFromTl(this: Message, act: tl.TypeMessageAction):
case 'messageActionChatEditPhoto': case 'messageActionChatEditPhoto':
return { return {
type: 'photo_changed', type: 'photo_changed',
photo: new Photo( photo: new Photo(this.client, act.photo as tl.RawPhoto),
this.client,
act.photo as tl.RawPhoto
),
} }
case 'messageActionChatDeletePhoto': case 'messageActionChatDeletePhoto':
return { return {
@ -390,12 +393,12 @@ export function _messageActionFromTl(this: Message, act: tl.TypeMessageAction):
} }
case 'messageActionScreenshotTaken': case 'messageActionScreenshotTaken':
return { return {
type: 'screenshot_taken' type: 'screenshot_taken',
} }
case 'messageActionBotAllowed': case 'messageActionBotAllowed':
return { return {
type: 'bot_allowed', type: 'bot_allowed',
domain: act.domain domain: act.domain,
} }
case 'messageActionGeoProximityReached': case 'messageActionGeoProximityReached':
if (act.fromId._ !== 'peerUser' || act.toId._ !== 'peerUser') { if (act.fromId._ !== 'peerUser' || act.toId._ !== 'peerUser') {
@ -405,7 +408,7 @@ export function _messageActionFromTl(this: Message, act: tl.TypeMessageAction):
type: 'geo_proximity', type: 'geo_proximity',
targetId: act.toId.userId, targetId: act.toId.userId,
userId: act.fromId.userId, userId: act.fromId.userId,
distance: act.distance distance: act.distance,
} }
} }
case 'messageActionGroupCall': case 'messageActionGroupCall':
@ -413,24 +416,24 @@ export function _messageActionFromTl(this: Message, act: tl.TypeMessageAction):
return { return {
type: 'group_call_ended', type: 'group_call_ended',
call: act.call, call: act.call,
duration: act.duration duration: act.duration,
} }
} else { } else {
return { return {
type: 'group_call_started', type: 'group_call_started',
call: act.call call: act.call,
} }
} }
case 'messageActionInviteToGroupCall': case 'messageActionInviteToGroupCall':
return { return {
type: 'group_call_invite', type: 'group_call_invite',
call: act.call, call: act.call,
userIds: act.users userIds: act.users,
} }
case 'messageActionSetMessagesTTL': case 'messageActionSetMessagesTTL':
return { return {
type: 'set_ttl', type: 'set_ttl',
period: act.period period: act.period,
} }
default: default:
return null return null

View file

@ -1,5 +1,4 @@
import { tl } from '@mtcute/tl' import { tl } from '@mtcute/tl'
import { User } from '../peers/user'
import { makeInspectable } from '../utils' import { makeInspectable } from '../utils'
const entityToType: Partial< const entityToType: Partial<

View file

@ -40,7 +40,10 @@ export type MessageMedia =
// todo: successful_payment, connected_website // todo: successful_payment, connected_website
/** @internal */ /** @internal */
export function _messageMediaFromTl(this: Message, m: tl.TypeMessageMedia): MessageMedia { export function _messageMediaFromTl(
this: Message,
m: tl.TypeMessageMedia
): MessageMedia {
switch (m._) { switch (m._) {
case 'messageMediaPhoto': case 'messageMediaPhoto':
if (!(m.photo?._ === 'photo')) return null if (!(m.photo?._ === 'photo')) return null

View file

@ -33,16 +33,22 @@ export const SearchFilters = {
Empty: { _: 'inputMessagesFilterEmpty' } as tl.TypeMessagesFilter, Empty: { _: 'inputMessagesFilterEmpty' } as tl.TypeMessagesFilter,
Photo: { _: 'inputMessagesFilterPhotos' } as tl.TypeMessagesFilter, Photo: { _: 'inputMessagesFilterPhotos' } as tl.TypeMessagesFilter,
Video: { _: 'inputMessagesFilterVideo' } as tl.TypeMessagesFilter, Video: { _: 'inputMessagesFilterVideo' } as tl.TypeMessagesFilter,
PhotoAndVideo: { _: 'inputMessagesFilterPhotoVideo' } as tl.TypeMessagesFilter, PhotoAndVideo: {
_: 'inputMessagesFilterPhotoVideo',
} as tl.TypeMessagesFilter,
Document: { _: 'inputMessagesFilterDocument' } as tl.TypeMessagesFilter, Document: { _: 'inputMessagesFilterDocument' } as tl.TypeMessagesFilter,
Url: { _: 'inputMessagesFilterUrl' } as tl.TypeMessagesFilter, Url: { _: 'inputMessagesFilterUrl' } as tl.TypeMessagesFilter,
Gif: { _: 'inputMessagesFilterGif' } as tl.TypeMessagesFilter, Gif: { _: 'inputMessagesFilterGif' } as tl.TypeMessagesFilter,
Voice: { _: 'inputMessagesFilterVoice' } as tl.TypeMessagesFilter, Voice: { _: 'inputMessagesFilterVoice' } as tl.TypeMessagesFilter,
Audio: { _: 'inputMessagesFilterMusic' } as tl.TypeMessagesFilter, Audio: { _: 'inputMessagesFilterMusic' } as tl.TypeMessagesFilter,
ChatPhotoChange: { _: 'inputMessagesFilterChatPhotos' } as tl.TypeMessagesFilter, ChatPhotoChange: {
_: 'inputMessagesFilterChatPhotos',
} as tl.TypeMessagesFilter,
Call: { _: 'inputMessagesFilterPhoneCalls' } as tl.TypeMessagesFilter, Call: { _: 'inputMessagesFilterPhoneCalls' } as tl.TypeMessagesFilter,
Round: { _: 'inputMessagesFilterRoundVideo' } as tl.TypeMessagesFilter, Round: { _: 'inputMessagesFilterRoundVideo' } as tl.TypeMessagesFilter,
RoundAndVoice: { _: 'inputMessagesFilterRoundVoice' } as tl.TypeMessagesFilter, RoundAndVoice: {
_: 'inputMessagesFilterRoundVoice',
} as tl.TypeMessagesFilter,
MyMention: { _: 'inputMessagesFilterMyMentions' } as tl.TypeMessagesFilter, MyMention: { _: 'inputMessagesFilterMyMentions' } as tl.TypeMessagesFilter,
Location: { _: 'inputMessagesFilterGeo' } as tl.TypeMessagesFilter, Location: { _: 'inputMessagesFilterGeo' } as tl.TypeMessagesFilter,
Contact: { _: 'inputMessagesFilterContacts' } as tl.TypeMessagesFilter, Contact: { _: 'inputMessagesFilterContacts' } as tl.TypeMessagesFilter,

View file

@ -107,7 +107,7 @@ export class StickerSet {
return { return {
_: 'inputStickerSetID', _: 'inputStickerSetID',
id: this.brief.id, id: this.brief.id,
accessHash: this.brief.accessHash accessHash: this.brief.accessHash,
} }
} }
@ -156,7 +156,7 @@ export class StickerSet {
const info: tl.Mutable<StickerSet.StickerInfo> = { const info: tl.Mutable<StickerSet.StickerInfo> = {
alt: sticker.emoji, alt: sticker.emoji,
emoji: '', // populated later emoji: '', // populated later
sticker sticker,
} }
this._stickers!.push(info) this._stickers!.push(info)
index[doc.id.toString()] = info index[doc.id.toString()] = info
@ -183,7 +183,9 @@ export class StickerSet {
* In case this object does not contain info about stickers (i.e. {@link isFull} = false) * In case this object does not contain info about stickers (i.e. {@link isFull} = false)
*/ */
getStickersByEmoji(emoji: string): StickerSet.StickerInfo[] { getStickersByEmoji(emoji: string): StickerSet.StickerInfo[] {
return this.stickers.filter(it => it.alt === emoji || it.emoji.indexOf(emoji) != -1) return this.stickers.filter(
(it) => it.alt === emoji || it.emoji.indexOf(emoji) != -1
)
} }
/** /**
@ -217,13 +219,14 @@ export class StickerSet {
if (idx < 0) idx = this.full!.documents.length + idx if (idx < 0) idx = this.full!.documents.length + idx
const doc = this.full!.documents[idx] as tl.RawDocument const doc = this.full!.documents[idx] as tl.RawDocument
if (!doc) throw new RangeError(`Sticker set does not have sticker ${idx}`) if (!doc)
throw new RangeError(`Sticker set does not have sticker ${idx}`)
return { return {
_: 'inputDocument', _: 'inputDocument',
id: doc.id, id: doc.id,
accessHash: doc.accessHash, accessHash: doc.accessHash,
fileReference: doc.fileReference fileReference: doc.fileReference,
} }
} }
@ -240,7 +243,9 @@ export class StickerSet {
* Sticker File ID. In case this is a full sticker set object, * Sticker File ID. In case this is a full sticker set object,
* you can also pass index (even negative), and that sticker will be removed * you can also pass index (even negative), and that sticker will be removed
*/ */
async deleteSticker(sticker: number | Parameters<TelegramClient['deleteStickerFromSet']>[0]): Promise<StickerSet> { async deleteSticker(
sticker: number | Parameters<TelegramClient['deleteStickerFromSet']>[0]
): Promise<StickerSet> {
if (typeof sticker === 'number') { if (typeof sticker === 'number') {
sticker = this._getInputDocument(sticker) sticker = this._getInputDocument(sticker)
} }
@ -262,7 +267,10 @@ export class StickerSet {
* you can also pass index (even negative), and that sticker will be removed * you can also pass index (even negative), and that sticker will be removed
* @param position New sticker position * @param position New sticker position
*/ */
async moveSticker(sticker: number | Parameters<TelegramClient['moveStickerInSet']>[0], position: number): Promise<StickerSet> { async moveSticker(
sticker: number | Parameters<TelegramClient['moveStickerInSet']>[0],
position: number
): Promise<StickerSet> {
if (typeof sticker === 'number') { if (typeof sticker === 'number') {
sticker = this._getInputDocument(sticker) sticker = this._getInputDocument(sticker)
} }
@ -284,7 +292,9 @@ export class StickerSet {
* you can also pass index (even negative), and that sticker * you can also pass index (even negative), and that sticker
* will be used as a thumb * will be used as a thumb
*/ */
async setThumb(thumb: number | Parameters<TelegramClient['setStickerSetThumb']>[1]): Promise<StickerSet> { async setThumb(
thumb: number | Parameters<TelegramClient['setStickerSetThumb']>[1]
): Promise<StickerSet> {
if (typeof thumb === 'number') { if (typeof thumb === 'number') {
thumb = this._getInputDocument(thumb) thumb = this._getInputDocument(thumb)
} }

View file

@ -351,35 +351,55 @@ function _actionFromTl(
return { return {
type: 'photo_changed', type: 'photo_changed',
old: new Photo(this.client, e.prevPhoto as tl.RawPhoto), old: new Photo(this.client, e.prevPhoto as tl.RawPhoto),
new: new Photo(this.client, e.newPhoto as tl.RawPhoto) new: new Photo(this.client, e.newPhoto as tl.RawPhoto),
} }
case 'channelAdminLogEventActionToggleInvites': case 'channelAdminLogEventActionToggleInvites':
return { return {
type: 'invites_toggled', type: 'invites_toggled',
old: !e.newValue, old: !e.newValue,
new: e.newValue new: e.newValue,
} }
case 'channelAdminLogEventActionToggleSignatures': case 'channelAdminLogEventActionToggleSignatures':
return { return {
type: 'signatures_toggled', type: 'signatures_toggled',
old: !e.newValue, old: !e.newValue,
new: e.newValue new: e.newValue,
} }
case 'channelAdminLogEventActionUpdatePinned': case 'channelAdminLogEventActionUpdatePinned':
return { return {
type: 'msg_pinned', type: 'msg_pinned',
message: new Message(this.client, e.message, this._users, this._chats) message: new Message(
this.client,
e.message,
this._users,
this._chats
),
} }
case 'channelAdminLogEventActionEditMessage': case 'channelAdminLogEventActionEditMessage':
return { return {
type: 'msg_edited', type: 'msg_edited',
old: new Message(this.client, e.prevMessage, this._users, this._chats), old: new Message(
new: new Message(this.client, e.newMessage, this._users, this._chats) this.client,
e.prevMessage,
this._users,
this._chats
),
new: new Message(
this.client,
e.newMessage,
this._users,
this._chats
),
} }
case 'channelAdminLogEventActionDeleteMessage': case 'channelAdminLogEventActionDeleteMessage':
return { return {
type: 'msg_deleted', type: 'msg_deleted',
message: new Message(this.client, e.message, this._users, this._chats) message: new Message(
this.client,
e.message,
this._users,
this._chats
),
} }
case 'channelAdminLogEventActionParticipantLeave': case 'channelAdminLogEventActionParticipantLeave':
return { type: 'user_left' } return { type: 'user_left' }
@ -391,65 +411,84 @@ function _actionFromTl(
case 'channelAdminLogEventActionParticipantToggleBan': case 'channelAdminLogEventActionParticipantToggleBan':
return { return {
type: 'user_perms_changed', type: 'user_perms_changed',
old: new ChatMember(this.client, e.prevParticipant, this._users), old: new ChatMember(
new: new ChatMember(this.client, e.newParticipant, this._users) this.client,
e.prevParticipant,
this._users
),
new: new ChatMember(this.client, e.newParticipant, this._users),
} }
case 'channelAdminLogEventActionParticipantToggleAdmin': case 'channelAdminLogEventActionParticipantToggleAdmin':
return { return {
type: 'user_admin_perms_changed', type: 'user_admin_perms_changed',
old: new ChatMember(this.client, e.prevParticipant, this._users), old: new ChatMember(
new: new ChatMember(this.client, e.newParticipant, this._users) this.client,
e.prevParticipant,
this._users
),
new: new ChatMember(this.client, e.newParticipant, this._users),
} }
case 'channelAdminLogEventActionChangeStickerSet': case 'channelAdminLogEventActionChangeStickerSet':
return { return {
type: 'stickerset_changed', type: 'stickerset_changed',
old: e.prevStickerset, old: e.prevStickerset,
new: e.newStickerset new: e.newStickerset,
} }
case 'channelAdminLogEventActionTogglePreHistoryHidden': case 'channelAdminLogEventActionTogglePreHistoryHidden':
return { return {
type: 'history_toggled', type: 'history_toggled',
old: !e.newValue, old: !e.newValue,
new: e.newValue new: e.newValue,
} }
case 'channelAdminLogEventActionDefaultBannedRights': case 'channelAdminLogEventActionDefaultBannedRights':
return { return {
type: 'def_perms_changed', type: 'def_perms_changed',
old: new ChatPermissions(e.prevBannedRights), old: new ChatPermissions(e.prevBannedRights),
new: new ChatPermissions(e.newBannedRights) new: new ChatPermissions(e.newBannedRights),
} }
case 'channelAdminLogEventActionStopPoll': case 'channelAdminLogEventActionStopPoll':
return { return {
type: 'poll_stopped', type: 'poll_stopped',
message: new Message(this.client, e.message, this._users, this._chats) message: new Message(
this.client,
e.message,
this._users,
this._chats
),
} }
case 'channelAdminLogEventActionChangeLinkedChat': case 'channelAdminLogEventActionChangeLinkedChat':
return { return {
type: 'linked_chat_changed', type: 'linked_chat_changed',
old: e.prevValue, old: e.prevValue,
new: e.newValue new: e.newValue,
} }
case 'channelAdminLogEventActionChangeLocation': case 'channelAdminLogEventActionChangeLocation':
return { return {
type: 'location_changed', type: 'location_changed',
old: e.prevValue._ === 'channelLocationEmpty' ? null : new ChatLocation(this.client, e.prevValue), old:
new: e.newValue._ === 'channelLocationEmpty' ? null : new ChatLocation(this.client, e.newValue), e.prevValue._ === 'channelLocationEmpty'
? null
: new ChatLocation(this.client, e.prevValue),
new:
e.newValue._ === 'channelLocationEmpty'
? null
: new ChatLocation(this.client, e.newValue),
} }
case 'channelAdminLogEventActionToggleSlowMode': case 'channelAdminLogEventActionToggleSlowMode':
return { return {
type: 'slow_mode_changed', type: 'slow_mode_changed',
old: e.prevValue, old: e.prevValue,
new: e.newValue new: e.newValue,
} }
case 'channelAdminLogEventActionStartGroupCall': case 'channelAdminLogEventActionStartGroupCall':
return { return {
type: 'call_started', type: 'call_started',
call: e.call call: e.call,
} }
case 'channelAdminLogEventActionDiscardGroupCall': case 'channelAdminLogEventActionDiscardGroupCall':
return { return {
type: 'call_ended', type: 'call_ended',
call: e.call call: e.call,
} }
case 'channelAdminLogEventActionParticipantMute': case 'channelAdminLogEventActionParticipantMute':
case 'channelAdminLogEventActionParticipantUnmute': case 'channelAdminLogEventActionParticipantUnmute':
@ -459,34 +498,34 @@ function _actionFromTl(
case 'channelAdminLogEventActionToggleGroupCallSetting': case 'channelAdminLogEventActionToggleGroupCallSetting':
return { return {
type: 'call_setting_changed', type: 'call_setting_changed',
joinMuted: e.joinMuted joinMuted: e.joinMuted,
} }
case 'channelAdminLogEventActionParticipantJoinByInvite': case 'channelAdminLogEventActionParticipantJoinByInvite':
return { return {
type: 'user_joined_invite', type: 'user_joined_invite',
link: new ChatInviteLink(this.client, e.invite, this._users) link: new ChatInviteLink(this.client, e.invite, this._users),
} }
case 'channelAdminLogEventActionExportedInviteDelete': case 'channelAdminLogEventActionExportedInviteDelete':
return { return {
type: 'invite_deleted', type: 'invite_deleted',
link: new ChatInviteLink(this.client, e.invite, this._users) link: new ChatInviteLink(this.client, e.invite, this._users),
} }
case 'channelAdminLogEventActionExportedInviteRevoke': case 'channelAdminLogEventActionExportedInviteRevoke':
return { return {
type: 'invite_revoked', type: 'invite_revoked',
link: new ChatInviteLink(this.client, e.invite, this._users) link: new ChatInviteLink(this.client, e.invite, this._users),
} }
case 'channelAdminLogEventActionExportedInviteEdit': case 'channelAdminLogEventActionExportedInviteEdit':
return { return {
type: 'invite_edited', type: 'invite_edited',
old: new ChatInviteLink(this.client, e.prevInvite, this._users), old: new ChatInviteLink(this.client, e.prevInvite, this._users),
new: new ChatInviteLink(this.client, e.newInvite, this._users) new: new ChatInviteLink(this.client, e.newInvite, this._users),
} }
case 'channelAdminLogEventActionChangeHistoryTTL': case 'channelAdminLogEventActionChangeHistoryTTL':
return { return {
type: 'ttl_changed', type: 'ttl_changed',
old: e.prevValue, old: e.prevValue,
new: e.newValue new: e.newValue,
} }
default: default:
return null return null

Some files were not shown because too many files have changed in this diff Show more