some changes
i've been wanting to name a commit like this for my entire life, lol. seriously though, a lot has changed: - extracted TL-related stuff to `@mtcute/tl-utils` and `@mtcute/tl-runtime`, rewrote codegen in TS - updated to layer 134, moved to int64 identifiers - rewritten networking (mtproto), rewritten updates handling - *lots* of refactoring still a very early version though, there are a lot of improvements to be made, but at least it runs, lol also tl-reference will not be updated anytime soon because i want to rewrite it
This commit is contained in:
parent
a834fbfa8d
commit
ec736f8590
244 changed files with 12560 additions and 6951 deletions
|
@ -36,6 +36,7 @@ module.exports = {
|
||||||
'@typescript-eslint/no-empty-function': 'off',
|
'@typescript-eslint/no-empty-function': 'off',
|
||||||
'@typescript-eslint/no-this-alias': 'off',
|
'@typescript-eslint/no-this-alias': 'off',
|
||||||
'prefer-rest-params': 'off',
|
'prefer-rest-params': 'off',
|
||||||
|
'no-prototype-builtins': 'off',
|
||||||
'@typescript-eslint/ban-types': 'off',
|
'@typescript-eslint/ban-types': 'off',
|
||||||
'@typescript-eslint/adjacent-overload-signatures': 'off',
|
'@typescript-eslint/adjacent-overload-signatures': 'off',
|
||||||
'@typescript-eslint/no-namespace': 'off',
|
'@typescript-eslint/no-namespace': 'off',
|
||||||
|
|
|
@ -12,12 +12,13 @@
|
||||||
"build": "tsc"
|
"build": "tsc"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/long": "^4.0.1",
|
||||||
"@types/node": "^15.12.1",
|
"@types/node": "^15.12.1",
|
||||||
"@mtcute/tl": "~1.131.0",
|
"@mtcute/tl": "~134.0",
|
||||||
"@mtcute/core": "^1.0.0",
|
"@mtcute/core": "^1.0.0",
|
||||||
"@mtcute/file-id": "^1.0.0",
|
"@mtcute/file-id": "^1.0.0",
|
||||||
"eager-async-pool": "^1.0.0",
|
"eager-async-pool": "^1.0.0",
|
||||||
"file-type": "^16.2.0",
|
"file-type": "^16.2.0",
|
||||||
"big-integer": "1.6.48"
|
"long": "^4.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ const ts = require('typescript')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const prettier = require('prettier')
|
const prettier = require('prettier')
|
||||||
// not the best way but who cares lol
|
|
||||||
const { createWriter } = require('../../tl/scripts/common')
|
|
||||||
const updates = require('./generate-updates')
|
const updates = require('./generate-updates')
|
||||||
|
|
||||||
const targetDir = path.join(__dirname, '../src')
|
const targetDir = path.join(__dirname, '../src')
|
||||||
|
@ -130,7 +128,7 @@ async function addSingleMethod(state, fileName) {
|
||||||
|
|
||||||
if (!isExported && !isPrivate) {
|
if (!isExported && !isPrivate) {
|
||||||
throwError(
|
throwError(
|
||||||
isExported,
|
stmt,
|
||||||
fileName,
|
fileName,
|
||||||
'Public methods MUST be exported.'
|
'Public methods MUST be exported.'
|
||||||
)
|
)
|
||||||
|
@ -228,6 +226,14 @@ async function addSingleMethod(state, fileName) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (stmt.kind === ts.SyntaxKind.InterfaceDeclaration) {
|
} else if (stmt.kind === ts.SyntaxKind.InterfaceDeclaration) {
|
||||||
|
if (isCopy) {
|
||||||
|
state.copy.push({
|
||||||
|
from: relPath,
|
||||||
|
code: stmt.getText()
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if (!checkForFlag(stmt, '@extension')) continue
|
if (!checkForFlag(stmt, '@extension')) continue
|
||||||
const isExported = (stmt.modifiers || []).find(
|
const isExported = (stmt.modifiers || []).find(
|
||||||
(mod) => mod.kind === 92 /* ExportKeyword */
|
(mod) => mod.kind === 92 /* ExportKeyword */
|
||||||
|
@ -260,7 +266,7 @@ async function addSingleMethod(state, fileName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const output = createWriter('../src/client.ts', __dirname)
|
const output = fs.createWriteStream(path.join(__dirname, '../src/client.ts'))
|
||||||
const state = {
|
const state = {
|
||||||
imports: {},
|
imports: {},
|
||||||
fields: [],
|
fields: [],
|
||||||
|
@ -282,23 +288,22 @@ async function main() {
|
||||||
output.write(
|
output.write(
|
||||||
'/* THIS FILE WAS AUTO-GENERATED */\n' +
|
'/* THIS FILE WAS AUTO-GENERATED */\n' +
|
||||||
"import { BaseTelegramClient } from '@mtcute/core'\n" +
|
"import { BaseTelegramClient } from '@mtcute/core'\n" +
|
||||||
"import { tl } from '@mtcute/tl'"
|
"import { tl } from '@mtcute/tl'\n"
|
||||||
)
|
)
|
||||||
Object.entries(state.imports).forEach(([module, items]) => {
|
Object.entries(state.imports).forEach(([module, items]) => {
|
||||||
items = [...items]
|
items = [...items]
|
||||||
output.write(`import { ${items.sort().join(', ')} } from '${module}'`)
|
output.write(`import { ${items.sort().join(', ')} } from '${module}'\n`)
|
||||||
})
|
})
|
||||||
|
|
||||||
output.write()
|
output.write('\n')
|
||||||
|
|
||||||
state.copy.forEach(({ from, code }) => {
|
state.copy.forEach(({ from, code }) => {
|
||||||
output.write(`// from ${from}\n${code}\n`)
|
output.write(`// from ${from}\n${code}\n`)
|
||||||
})
|
})
|
||||||
|
|
||||||
output.write(
|
output.write(
|
||||||
'\nexport interface TelegramClient extends BaseTelegramClient {'
|
'\nexport interface TelegramClient extends BaseTelegramClient {\n'
|
||||||
)
|
)
|
||||||
output.tab()
|
|
||||||
|
|
||||||
output.write(`/**
|
output.write(`/**
|
||||||
* Register a raw update handler
|
* Register a raw update handler
|
||||||
|
@ -306,14 +311,14 @@ async function main() {
|
||||||
* @param name Event name
|
* @param name Event name
|
||||||
* @param handler Raw update handler
|
* @param handler Raw update handler
|
||||||
*/
|
*/
|
||||||
on(name: 'raw_update', handler: ((upd: tl.TypeUpdate | tl.TypeMessage, users: UsersIndex, chats: ChatsIndex) => void)): this
|
on(name: 'raw_update', handler: ((upd: tl.TypeUpdate | tl.TypeMessage, peers: PeersIndex) => void)): this
|
||||||
/**
|
/**
|
||||||
* Register a parsed update handler
|
* Register a parsed update handler
|
||||||
*
|
*
|
||||||
* @param name Event name
|
* @param name Event name
|
||||||
* @param handler Raw update handler
|
* @param handler Raw update handler
|
||||||
*/
|
*/
|
||||||
on(name: 'update', handler: ((upd: ParsedUpdate) => void)): this`)
|
on(name: 'update', handler: ((upd: ParsedUpdate) => void)): this\n`)
|
||||||
|
|
||||||
updates.types.forEach((type) => {
|
updates.types.forEach((type) => {
|
||||||
output.write(`/**
|
output.write(`/**
|
||||||
|
@ -322,7 +327,7 @@ async function main() {
|
||||||
* @param name Event name
|
* @param name Event name
|
||||||
* @param handler ${updates.toSentence(type, 'full')}
|
* @param handler ${updates.toSentence(type, 'full')}
|
||||||
*/
|
*/
|
||||||
on(name: '${type.typeName}', handler: ((upd: ${type.updateType}) => void)): this`)
|
on(name: '${type.typeName}', handler: ((upd: ${type.updateType}) => void)): this\n`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -441,10 +446,10 @@ on(name: '${type.typeName}', handler: ((upd: ${type.updateType}) => void)): this
|
||||||
if (!isPrivate && !hasOverloads) {
|
if (!isPrivate && !hasOverloads) {
|
||||||
if (!comment.match(/\/\*\*?\s*\*\//))
|
if (!comment.match(/\/\*\*?\s*\*\//))
|
||||||
// empty comment, no need to write it
|
// empty comment, no need to write it
|
||||||
output.write(comment)
|
output.write(comment + '\n')
|
||||||
|
|
||||||
output.write(
|
output.write(
|
||||||
`${name}${generics}(${parameters})${returnType}`
|
`${name}${generics}(${parameters})${returnType}\n`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,27 +461,22 @@ on(name: '${type.typeName}', handler: ((upd: ${type.updateType}) => void)): this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
output.untab()
|
|
||||||
output.write('}')
|
|
||||||
|
|
||||||
output.write(
|
|
||||||
'/** @internal */\nexport class TelegramClient extends BaseTelegramClient {'
|
|
||||||
)
|
|
||||||
output.tab()
|
|
||||||
|
|
||||||
state.fields.forEach(({ code }) => output.write('protected ' + code))
|
|
||||||
|
|
||||||
output.write('constructor(opts: BaseTelegramClient.Options) {')
|
|
||||||
output.tab()
|
|
||||||
output.write('super(opts)')
|
|
||||||
state.init.forEach((code) => {
|
|
||||||
output.write(code)
|
|
||||||
})
|
|
||||||
output.untab()
|
|
||||||
output.write('}\n')
|
output.write('}\n')
|
||||||
|
|
||||||
classContents.forEach((line) => output.write(line))
|
output.write(
|
||||||
output.untab()
|
'/** @internal */\nexport class TelegramClient extends BaseTelegramClient {\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
state.fields.forEach(({ code }) => output.write(`protected ${code}\n`))
|
||||||
|
|
||||||
|
output.write('constructor(opts: BaseTelegramClient.Options) {\n')
|
||||||
|
output.write('super(opts)\n')
|
||||||
|
state.init.forEach((code) => {
|
||||||
|
output.write(code + '\n')
|
||||||
|
})
|
||||||
|
output.write('}\n')
|
||||||
|
|
||||||
|
classContents.forEach((line) => output.write(line + '\n'))
|
||||||
output.write('}')
|
output.write('}')
|
||||||
|
|
||||||
// format the resulting file with prettier
|
// format the resulting file with prettier
|
||||||
|
|
|
@ -1,11 +1,24 @@
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const prettier = require('prettier')
|
const prettier = require('prettier')
|
||||||
const {
|
|
||||||
snakeToCamel,
|
const snakeToCamel = (s) => {
|
||||||
camelToPascal,
|
return s.replace(/(?<!^|_)(_[a-z0-9])/gi, ($1) => {
|
||||||
camelToSnake,
|
return $1.substr(1).toUpperCase()
|
||||||
} = require('../../tl/scripts/common')
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const camelToPascal = (s) =>
|
||||||
|
s[0].toUpperCase() + s.substr(1)
|
||||||
|
|
||||||
|
const camelToSnake = (s) => {
|
||||||
|
return s.replace(
|
||||||
|
/(?<=[a-zA-Z0-9])([A-Z0-9]+(?=[A-Z]|$)|[A-Z0-9])/g,
|
||||||
|
($1) => {
|
||||||
|
return '_' + $1.toLowerCase()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function parseUpdateTypes() {
|
function parseUpdateTypes() {
|
||||||
const lines = fs
|
const lines = fs
|
||||||
|
|
|
@ -145,14 +145,31 @@ import { getInstalledStickers } from './methods/stickers/get-installed-stickers'
|
||||||
import { getStickerSet } from './methods/stickers/get-sticker-set'
|
import { getStickerSet } from './methods/stickers/get-sticker-set'
|
||||||
import { moveStickerInSet } from './methods/stickers/move-sticker-in-set'
|
import { moveStickerInSet } from './methods/stickers/move-sticker-in-set'
|
||||||
import { setStickerSetThumb } from './methods/stickers/set-sticker-set-thumb'
|
import { setStickerSetThumb } from './methods/stickers/set-sticker-set-thumb'
|
||||||
|
import { ConditionVariable } from '@mtcute/core/src/utils/condition-variable'
|
||||||
|
import {
|
||||||
|
AsyncLock,
|
||||||
|
Deque,
|
||||||
|
MaybeArray,
|
||||||
|
MaybeAsync,
|
||||||
|
SessionConnection,
|
||||||
|
SortedLinkedList,
|
||||||
|
} from '@mtcute/core'
|
||||||
|
import { RpsMeter } from './utils/rps-meter'
|
||||||
import {
|
import {
|
||||||
_dispatchUpdate,
|
_dispatchUpdate,
|
||||||
_fetchUpdatesState,
|
_fetchUpdatesState,
|
||||||
_handleUpdate,
|
_handleUpdate,
|
||||||
_keepAliveAction,
|
_keepAliveAction,
|
||||||
_loadStorage,
|
_loadStorage,
|
||||||
|
_onStop,
|
||||||
_saveStorage,
|
_saveStorage,
|
||||||
|
_updatesLoop,
|
||||||
catchUp,
|
catchUp,
|
||||||
|
enableRps,
|
||||||
|
getCurrentRpsIncoming,
|
||||||
|
getCurrentRpsProcessing,
|
||||||
|
startUpdatesLoop,
|
||||||
|
stopUpdatesLoop,
|
||||||
} from './methods/updates'
|
} from './methods/updates'
|
||||||
import { blockUser } from './methods/users/block-user'
|
import { blockUser } from './methods/users/block-user'
|
||||||
import { deleteProfilePhotos } from './methods/users/delete-profile-photos'
|
import { deleteProfilePhotos } from './methods/users/delete-profile-photos'
|
||||||
|
@ -181,7 +198,6 @@ import {
|
||||||
ChatMember,
|
ChatMember,
|
||||||
ChatMemberUpdate,
|
ChatMemberUpdate,
|
||||||
ChatPreview,
|
ChatPreview,
|
||||||
ChatsIndex,
|
|
||||||
ChosenInlineResult,
|
ChosenInlineResult,
|
||||||
Conversation,
|
Conversation,
|
||||||
DeleteMessageUpdate,
|
DeleteMessageUpdate,
|
||||||
|
@ -203,6 +219,7 @@ import {
|
||||||
ParsedUpdate,
|
ParsedUpdate,
|
||||||
PartialExcept,
|
PartialExcept,
|
||||||
PartialOnly,
|
PartialOnly,
|
||||||
|
PeersIndex,
|
||||||
Photo,
|
Photo,
|
||||||
Poll,
|
Poll,
|
||||||
PollUpdate,
|
PollUpdate,
|
||||||
|
@ -219,17 +236,27 @@ import {
|
||||||
User,
|
User,
|
||||||
UserStatusUpdate,
|
UserStatusUpdate,
|
||||||
UserTypingUpdate,
|
UserTypingUpdate,
|
||||||
UsersIndex,
|
|
||||||
} from './types'
|
} from './types'
|
||||||
import {
|
|
||||||
AsyncLock,
|
|
||||||
MaybeArray,
|
|
||||||
MaybeAsync,
|
|
||||||
TelegramConnection,
|
|
||||||
} from '@mtcute/core'
|
|
||||||
import { tdFileId } from '@mtcute/file-id'
|
import { tdFileId } from '@mtcute/file-id'
|
||||||
import { Logger } from '@mtcute/core/src/utils/logger'
|
import { Logger } from '@mtcute/core/src/utils/logger'
|
||||||
|
|
||||||
|
// from methods/updates.ts
|
||||||
|
interface PendingUpdateContainer {
|
||||||
|
upd: tl.TypeUpdates
|
||||||
|
seqStart: number
|
||||||
|
seqEnd: number
|
||||||
|
}
|
||||||
|
// from methods/updates.ts
|
||||||
|
interface PendingUpdate {
|
||||||
|
update: tl.TypeUpdate
|
||||||
|
channelId?: number
|
||||||
|
pts?: number
|
||||||
|
ptsBefore?: number
|
||||||
|
qtsBefore?: number
|
||||||
|
timeout?: number
|
||||||
|
peers?: PeersIndex
|
||||||
|
}
|
||||||
|
|
||||||
export interface TelegramClient extends BaseTelegramClient {
|
export interface TelegramClient extends BaseTelegramClient {
|
||||||
/**
|
/**
|
||||||
* Register a raw update handler
|
* Register a raw update handler
|
||||||
|
@ -241,8 +268,7 @@ export interface TelegramClient extends BaseTelegramClient {
|
||||||
name: 'raw_update',
|
name: 'raw_update',
|
||||||
handler: (
|
handler: (
|
||||||
upd: tl.TypeUpdate | tl.TypeMessage,
|
upd: tl.TypeUpdate | tl.TypeMessage,
|
||||||
users: UsersIndex,
|
peers: PeersIndex
|
||||||
chats: ChatsIndex
|
|
||||||
) => void
|
) => void
|
||||||
): this
|
): this
|
||||||
/**
|
/**
|
||||||
|
@ -3268,12 +3294,58 @@ export interface TelegramClient extends BaseTelegramClient {
|
||||||
progressCallback?: (uploaded: number, total: number) => void
|
progressCallback?: (uploaded: number, total: number) => void
|
||||||
}
|
}
|
||||||
): Promise<StickerSet>
|
): Promise<StickerSet>
|
||||||
|
/**
|
||||||
|
* Enable RPS meter.
|
||||||
|
* Only available in NodeJS v10.7.0 and newer
|
||||||
|
*
|
||||||
|
* > **Note**: This may have negative impact on performance
|
||||||
|
*
|
||||||
|
* @param size Sampling size
|
||||||
|
* @param time Window time
|
||||||
|
*/
|
||||||
|
enableRps(size?: number, time?: number): void
|
||||||
|
/**
|
||||||
|
* Get current average incoming RPS
|
||||||
|
*
|
||||||
|
* Incoming RPS is calculated based on
|
||||||
|
* incoming update containers. Normally,
|
||||||
|
* they should be around the same, except
|
||||||
|
* rare situations when processing rps
|
||||||
|
* may peak.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
getCurrentRpsIncoming(): number
|
||||||
|
/**
|
||||||
|
* Get current average processing RPS
|
||||||
|
*
|
||||||
|
* Processing RPS is calculated based on
|
||||||
|
* dispatched updates. Normally,
|
||||||
|
* they should be around the same, except
|
||||||
|
* rare situations when processing rps
|
||||||
|
* may peak.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
getCurrentRpsProcessing(): number
|
||||||
|
/**
|
||||||
|
* **ADVANCED**
|
||||||
|
*
|
||||||
|
* Manually start updates loop.
|
||||||
|
* Usually done automatically inside {@link start}
|
||||||
|
*/
|
||||||
|
startUpdatesLoop(): void
|
||||||
|
/**
|
||||||
|
* **ADVANCED**
|
||||||
|
*
|
||||||
|
* Manually stop updates loop.
|
||||||
|
* Usually done automatically when stopping the client with {@link close}
|
||||||
|
*/
|
||||||
|
stopUpdatesLoop(): void
|
||||||
_handleUpdate(update: tl.TypeUpdates, noDispatch?: boolean): void
|
_handleUpdate(update: tl.TypeUpdates, noDispatch?: boolean): void
|
||||||
/**
|
/**
|
||||||
* Catch up with the server by loading missed updates.
|
* Catch up with the server by loading missed updates.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
catchUp(): Promise<void>
|
catchUp(): void
|
||||||
/**
|
/**
|
||||||
* Block a user
|
* Block a user
|
||||||
*
|
*
|
||||||
|
@ -3413,8 +3485,12 @@ export interface TelegramClient extends BaseTelegramClient {
|
||||||
* Useful when an `InputPeer` is needed.
|
* Useful when an `InputPeer` is needed.
|
||||||
*
|
*
|
||||||
* @param peerId The peer identifier that you want to extract the `InputPeer` from.
|
* @param peerId The peer identifier that you want to extract the `InputPeer` from.
|
||||||
|
* @param force (default: `false`) Whether to force re-fetch the peer from the server
|
||||||
*/
|
*/
|
||||||
resolvePeer(peerId: InputPeerLike): Promise<tl.TypeInputPeer>
|
resolvePeer(
|
||||||
|
peerId: InputPeerLike,
|
||||||
|
force?: boolean
|
||||||
|
): Promise<tl.TypeInputPeer>
|
||||||
/**
|
/**
|
||||||
* Change user status to offline or online
|
* Change user status to offline or online
|
||||||
*
|
*
|
||||||
|
@ -3483,11 +3559,21 @@ export class TelegramClient extends BaseTelegramClient {
|
||||||
protected _selfUsername: string | null
|
protected _selfUsername: string | null
|
||||||
protected _pendingConversations: Record<number, Conversation[]>
|
protected _pendingConversations: Record<number, Conversation[]>
|
||||||
protected _hasConversations: boolean
|
protected _hasConversations: boolean
|
||||||
protected _downloadConnections: Record<number, TelegramConnection>
|
protected _downloadConnections: Record<number, SessionConnection>
|
||||||
protected _connectionsForInline: Record<number, TelegramConnection>
|
protected _connectionsForInline: Record<number, SessionConnection>
|
||||||
protected _parseModes: Record<string, IMessageEntityParser>
|
protected _parseModes: Record<string, IMessageEntityParser>
|
||||||
protected _defaultParseMode: string | null
|
protected _defaultParseMode: string | null
|
||||||
|
protected _updatesLoopActive: boolean
|
||||||
|
protected _updatesLoopCv: ConditionVariable
|
||||||
|
protected _pendingUpdateContainers: SortedLinkedList<PendingUpdateContainer>
|
||||||
|
protected _pendingPtsUpdates: SortedLinkedList<PendingUpdate>
|
||||||
|
protected _pendingPtsUpdatesPostponed: SortedLinkedList<PendingUpdate>
|
||||||
|
protected _pendingQtsUpdates: SortedLinkedList<PendingUpdate>
|
||||||
|
protected _pendingQtsUpdatesPostponed: SortedLinkedList<PendingUpdate>
|
||||||
|
protected _pendingUnorderedUpdates: Deque<PendingUpdate>
|
||||||
protected _updLock: AsyncLock
|
protected _updLock: AsyncLock
|
||||||
|
protected _rpsIncoming?: RpsMeter
|
||||||
|
protected _rpsProcessing?: RpsMeter
|
||||||
protected _pts?: number
|
protected _pts?: number
|
||||||
protected _qts?: number
|
protected _qts?: number
|
||||||
protected _date?: number
|
protected _date?: number
|
||||||
|
@ -3506,12 +3592,33 @@ export class TelegramClient extends BaseTelegramClient {
|
||||||
this._userId = null
|
this._userId = null
|
||||||
this._isBot = false
|
this._isBot = false
|
||||||
this._selfUsername = null
|
this._selfUsername = null
|
||||||
|
this.log.prefix = '[USER N/A] '
|
||||||
this._pendingConversations = {}
|
this._pendingConversations = {}
|
||||||
this._hasConversations = false
|
this._hasConversations = false
|
||||||
this._downloadConnections = {}
|
this._downloadConnections = {}
|
||||||
this._connectionsForInline = {}
|
this._connectionsForInline = {}
|
||||||
this._parseModes = {}
|
this._parseModes = {}
|
||||||
this._defaultParseMode = null
|
this._defaultParseMode = null
|
||||||
|
this._updatesLoopActive = false
|
||||||
|
this._updatesLoopCv = new ConditionVariable()
|
||||||
|
|
||||||
|
this._pendingUpdateContainers = new SortedLinkedList(
|
||||||
|
(a, b) => a.seqStart - b.seqStart
|
||||||
|
)
|
||||||
|
this._pendingPtsUpdates = new SortedLinkedList(
|
||||||
|
(a, b) => a.ptsBefore! - b.ptsBefore!
|
||||||
|
)
|
||||||
|
this._pendingPtsUpdatesPostponed = new SortedLinkedList(
|
||||||
|
(a, b) => a.ptsBefore! - b.ptsBefore!
|
||||||
|
)
|
||||||
|
this._pendingQtsUpdates = new SortedLinkedList(
|
||||||
|
(a, b) => a.qtsBefore! - b.qtsBefore!
|
||||||
|
)
|
||||||
|
this._pendingQtsUpdatesPostponed = new SortedLinkedList(
|
||||||
|
(a, b) => a.qtsBefore! - b.qtsBefore!
|
||||||
|
)
|
||||||
|
this._pendingUnorderedUpdates = new Deque()
|
||||||
|
|
||||||
this._updLock = new AsyncLock()
|
this._updLock = new AsyncLock()
|
||||||
// we dont need to initialize state fields since
|
// we dont need to initialize state fields since
|
||||||
// they are always loaded either from the server, or from storage.
|
// they are always loaded either from the server, or from storage.
|
||||||
|
@ -3527,7 +3634,6 @@ export class TelegramClient extends BaseTelegramClient {
|
||||||
|
|
||||||
this._updsLog = this.log.create('updates')
|
this._updsLog = this.log.create('updates')
|
||||||
}
|
}
|
||||||
|
|
||||||
acceptTos = acceptTos
|
acceptTos = acceptTos
|
||||||
checkPassword = checkPassword
|
checkPassword = checkPassword
|
||||||
getPasswordHint = getPasswordHint
|
getPasswordHint = getPasswordHint
|
||||||
|
@ -3667,12 +3773,19 @@ export class TelegramClient extends BaseTelegramClient {
|
||||||
getStickerSet = getStickerSet
|
getStickerSet = getStickerSet
|
||||||
moveStickerInSet = moveStickerInSet
|
moveStickerInSet = moveStickerInSet
|
||||||
setStickerSetThumb = setStickerSetThumb
|
setStickerSetThumb = setStickerSetThumb
|
||||||
|
enableRps = enableRps
|
||||||
|
getCurrentRpsIncoming = getCurrentRpsIncoming
|
||||||
|
getCurrentRpsProcessing = getCurrentRpsProcessing
|
||||||
protected _fetchUpdatesState = _fetchUpdatesState
|
protected _fetchUpdatesState = _fetchUpdatesState
|
||||||
protected _loadStorage = _loadStorage
|
protected _loadStorage = _loadStorage
|
||||||
|
startUpdatesLoop = startUpdatesLoop
|
||||||
|
stopUpdatesLoop = stopUpdatesLoop
|
||||||
|
protected _onStop = _onStop
|
||||||
protected _saveStorage = _saveStorage
|
protected _saveStorage = _saveStorage
|
||||||
protected _dispatchUpdate = _dispatchUpdate
|
protected _dispatchUpdate = _dispatchUpdate
|
||||||
_handleUpdate = _handleUpdate
|
_handleUpdate = _handleUpdate
|
||||||
catchUp = catchUp
|
catchUp = catchUp
|
||||||
|
protected _updatesLoop = _updatesLoop
|
||||||
protected _keepAliveAction = _keepAliveAction
|
protected _keepAliveAction = _keepAliveAction
|
||||||
blockUser = blockUser
|
blockUser = blockUser
|
||||||
deleteProfilePhotos = deleteProfilePhotos
|
deleteProfilePhotos = deleteProfilePhotos
|
||||||
|
|
|
@ -32,8 +32,7 @@ import {
|
||||||
Photo,
|
Photo,
|
||||||
ChatEvent,
|
ChatEvent,
|
||||||
ChatInviteLink,
|
ChatInviteLink,
|
||||||
UsersIndex,
|
PeersIndex,
|
||||||
ChatsIndex,
|
|
||||||
GameHighScore,
|
GameHighScore,
|
||||||
ArrayWithTotal,
|
ArrayWithTotal,
|
||||||
BotCommands,
|
BotCommands,
|
||||||
|
@ -60,7 +59,7 @@ import {
|
||||||
import {
|
import {
|
||||||
MaybeArray,
|
MaybeArray,
|
||||||
MaybeAsync,
|
MaybeAsync,
|
||||||
TelegramConnection,
|
SessionConnection,
|
||||||
AsyncLock,
|
AsyncLock,
|
||||||
} from '@mtcute/core'
|
} from '@mtcute/core'
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
|
import { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
// @extension
|
// @extension
|
||||||
interface AuthState {
|
interface AuthState {
|
||||||
|
@ -17,4 +18,5 @@ function _initializeAuthState(this: TelegramClient) {
|
||||||
this._userId = null
|
this._userId = null
|
||||||
this._isBot = false
|
this._isBot = false
|
||||||
this._selfUsername = null
|
this._selfUsername = null
|
||||||
|
this.log.prefix = '[USER N/A] '
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,11 +37,17 @@ export async function checkPassword(
|
||||||
'user'
|
'user'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
this.log.prefix = `[USER ${this._userId}] `
|
||||||
this._userId = res.user.id
|
this._userId = res.user.id
|
||||||
this._isBot = false
|
this._isBot = false
|
||||||
this._selfChanged = true
|
this._selfChanged = true
|
||||||
|
this._selfUsername = res.user.username ?? null
|
||||||
await this._fetchUpdatesState()
|
await this._fetchUpdatesState()
|
||||||
await this._saveStorage()
|
await this._saveStorage()
|
||||||
|
|
||||||
|
// telegram ignores invokeWithoutUpdates for auth methods
|
||||||
|
if (this._disableUpdates) this.primaryConnection._resetSession()
|
||||||
|
else this.startUpdatesLoop()
|
||||||
|
|
||||||
return new User(this, res.user)
|
return new User(this, res.user)
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ export async function signInBot(
|
||||||
'user'
|
'user'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
this.log.prefix = `[USER ${this._userId}] `
|
||||||
this._userId = res.user.id
|
this._userId = res.user.id
|
||||||
this._isBot = true
|
this._isBot = true
|
||||||
this._selfUsername = res.user.username!
|
this._selfUsername = res.user.username!
|
||||||
|
@ -40,5 +41,9 @@ export async function signInBot(
|
||||||
await this._fetchUpdatesState()
|
await this._fetchUpdatesState()
|
||||||
await this._saveStorage()
|
await this._saveStorage()
|
||||||
|
|
||||||
|
// telegram ignores invokeWithoutUpdates for auth methods
|
||||||
|
if (this._disableUpdates) this.primaryConnection._resetSession()
|
||||||
|
else this.startUpdatesLoop()
|
||||||
|
|
||||||
return new User(this, res.user)
|
return new User(this, res.user)
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ export async function signIn(
|
||||||
|
|
||||||
assertTypeIs('signIn (@ auth.signIn -> user)', res.user, 'user')
|
assertTypeIs('signIn (@ auth.signIn -> user)', res.user, 'user')
|
||||||
|
|
||||||
|
this.log.prefix = `[USER ${this._userId}] `
|
||||||
this._userId = res.user.id
|
this._userId = res.user.id
|
||||||
this._isBot = false
|
this._isBot = false
|
||||||
this._selfChanged = true
|
this._selfChanged = true
|
||||||
|
@ -48,5 +49,9 @@ export async function signIn(
|
||||||
await this._fetchUpdatesState()
|
await this._fetchUpdatesState()
|
||||||
await this._saveStorage()
|
await this._saveStorage()
|
||||||
|
|
||||||
|
// telegram ignores invokeWithoutUpdates for auth methods
|
||||||
|
if (this._disableUpdates) this.primaryConnection._resetSession()
|
||||||
|
else this.startUpdatesLoop()
|
||||||
|
|
||||||
return new User(this, res.user)
|
return new User(this, res.user)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,11 +32,16 @@ export async function signUp(
|
||||||
assertTypeIs('signUp (@ auth.signUp)', res, 'auth.authorization')
|
assertTypeIs('signUp (@ auth.signUp)', res, 'auth.authorization')
|
||||||
assertTypeIs('signUp (@ auth.signUp -> user)', res.user, 'user')
|
assertTypeIs('signUp (@ auth.signUp -> user)', res.user, 'user')
|
||||||
|
|
||||||
|
this.log.prefix = `[USER ${this._userId}] `
|
||||||
this._userId = res.user.id
|
this._userId = res.user.id
|
||||||
this._isBot = false
|
this._isBot = false
|
||||||
this._selfChanged = true
|
this._selfChanged = true
|
||||||
await this._fetchUpdatesState()
|
await this._fetchUpdatesState()
|
||||||
await this._saveStorage()
|
await this._saveStorage()
|
||||||
|
|
||||||
|
// telegram ignores invokeWithoutUpdates for auth methods
|
||||||
|
if (this._disableUpdates) this.primaryConnection._resetSession()
|
||||||
|
else this.startUpdatesLoop()
|
||||||
|
|
||||||
return new User(this, res.user)
|
return new User(this, res.user)
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,15 +148,28 @@ export async function start(
|
||||||
|
|
||||||
// user is already authorized
|
// user is already authorized
|
||||||
|
|
||||||
|
this.log.prefix = `[USER ${me.id}] `
|
||||||
|
this.log.info(
|
||||||
|
'Logged in as %s (ID: %s, username: %s, bot: %s)',
|
||||||
|
me.displayName,
|
||||||
|
me.id,
|
||||||
|
me.username,
|
||||||
|
me.isBot
|
||||||
|
)
|
||||||
|
|
||||||
if (!this._disableUpdates) {
|
if (!this._disableUpdates) {
|
||||||
this._catchUpChannels = !!params.catchUp
|
this._catchUpChannels = !!params.catchUp
|
||||||
|
|
||||||
if (params.catchUp) {
|
if (!params.catchUp) {
|
||||||
await this.catchUp()
|
|
||||||
} else {
|
|
||||||
// otherwise we will catch up as soon as we receive a new update
|
// otherwise we will catch up as soon as we receive a new update
|
||||||
await this._fetchUpdatesState()
|
await this._fetchUpdatesState()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.startUpdatesLoop()
|
||||||
|
|
||||||
|
if (params.catchUp) {
|
||||||
|
this.catchUp()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return me
|
return me
|
||||||
|
@ -165,9 +178,7 @@ export async function start(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!params.phone && !params.botToken)
|
if (!params.phone && !params.botToken)
|
||||||
throw new MtArgumentError(
|
throw new MtArgumentError('Neither phone nor bot token were provided')
|
||||||
'Neither phone nor bot token were provided'
|
|
||||||
)
|
|
||||||
|
|
||||||
let phone = params.phone ? await resolveMaybeDynamic(params.phone) : null
|
let phone = params.phone ? await resolveMaybeDynamic(params.phone) : null
|
||||||
if (phone) {
|
if (phone) {
|
||||||
|
@ -249,9 +260,7 @@ export async function start(
|
||||||
result = await this.checkPassword(password)
|
result = await this.checkPassword(password)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (typeof params.password !== 'function') {
|
if (typeof params.password !== 'function') {
|
||||||
throw new MtArgumentError(
|
throw new MtArgumentError('Provided password was invalid')
|
||||||
'Provided password was invalid'
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e instanceof PasswordHashInvalidError) {
|
if (e instanceof PasswordHashInvalidError) {
|
||||||
|
|
|
@ -3,12 +3,10 @@ import {
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
MtInvalidPeerTypeError,
|
MtInvalidPeerTypeError,
|
||||||
GameHighScore,
|
GameHighScore,
|
||||||
|
PeersIndex,
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import {
|
import { normalizeToInputUser } from '../../utils/peer-utils'
|
||||||
createUsersChatsIndex,
|
|
||||||
normalizeToInputUser,
|
|
||||||
} from '../../utils/peer-utils'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get high scores of a game
|
* Get high scores of a game
|
||||||
|
@ -43,9 +41,9 @@ export async function getGameHighScores(
|
||||||
userId: user,
|
userId: user,
|
||||||
})
|
})
|
||||||
|
|
||||||
const { users } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
return res.scores.map((score) => new GameHighScore(this, score, users))
|
return res.scores.map((score) => new GameHighScore(this, score, peers))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,7 +79,7 @@ export async function getInlineGameHighScores(
|
||||||
{ connection }
|
{ connection }
|
||||||
)
|
)
|
||||||
|
|
||||||
const { users } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
return res.scores.map((score) => new GameHighScore(this, score, users))
|
return res.scores.map((score) => new GameHighScore(this, score, peers))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { Chat, MtTypeAssertionError } from '../../types'
|
import { Chat } from '../../types'
|
||||||
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { MaybeArray } from '@mtcute/core'
|
import { MaybeArray } from '@mtcute/core'
|
||||||
import { Chat, InputPeerLike, MtTypeAssertionError } from '../../types'
|
import { Chat, InputPeerLike } from '../../types'
|
||||||
import { normalizeToInputUser } from '../../utils/peer-utils'
|
import { normalizeToInputUser } from '../../utils/peer-utils'
|
||||||
import { tl } from '@mtcute/tl'
|
|
||||||
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { Chat, MtTypeAssertionError } from '../../types'
|
import { Chat } from '../../types'
|
||||||
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,16 +2,15 @@ import { TelegramClient } from '../../client'
|
||||||
import {
|
import {
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
MtInvalidPeerTypeError,
|
MtInvalidPeerTypeError,
|
||||||
ChatEvent,
|
ChatEvent, PeersIndex,
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { MaybeArray } from '@mtcute/core'
|
import { MaybeArray } from '@mtcute/core'
|
||||||
import bigInt from 'big-integer'
|
|
||||||
import {
|
import {
|
||||||
createUsersChatsIndex,
|
|
||||||
normalizeToInputChannel,
|
normalizeToInputChannel,
|
||||||
normalizeToInputUser,
|
normalizeToInputUser,
|
||||||
} from '../../utils/peer-utils'
|
} from '../../utils/peer-utils'
|
||||||
|
import Long from 'long'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get chat event log ("Recent actions" in official
|
* Get chat event log ("Recent actions" in official
|
||||||
|
@ -89,8 +88,8 @@ export async function* getChatEventLog(
|
||||||
if (!channel) throw new MtInvalidPeerTypeError(chatId, 'channel')
|
if (!channel) throw new MtInvalidPeerTypeError(chatId, 'channel')
|
||||||
|
|
||||||
let current = 0
|
let current = 0
|
||||||
let maxId = params.maxId ?? bigInt.zero
|
let maxId = params.maxId ?? Long.ZERO
|
||||||
const minId = params.minId ?? bigInt.zero
|
const minId = params.minId ?? Long.ZERO
|
||||||
const query = params.query ?? ''
|
const query = params.query ?? ''
|
||||||
|
|
||||||
const total = params.limit || Infinity
|
const total = params.limit || Infinity
|
||||||
|
@ -216,12 +215,12 @@ export async function* getChatEventLog(
|
||||||
|
|
||||||
if (!res.events.length) break
|
if (!res.events.length) break
|
||||||
|
|
||||||
const { users, chats } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
const last = res.events[res.events.length - 1]
|
const last = res.events[res.events.length - 1]
|
||||||
maxId = last.id
|
maxId = last.id
|
||||||
|
|
||||||
for (const evt of res.events) {
|
for (const evt of res.events) {
|
||||||
const parsed = new ChatEvent(this, evt, users, chats)
|
const parsed = new ChatEvent(this, evt, peers)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
localFilter &&
|
localFilter &&
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { InputPeerLike, MtInvalidPeerTypeError } from '../../types'
|
import { InputPeerLike, MtInvalidPeerTypeError, PeersIndex } from '../../types'
|
||||||
import {
|
import {
|
||||||
createUsersChatsIndex,
|
|
||||||
isInputPeerChannel,
|
isInputPeerChannel,
|
||||||
isInputPeerChat,
|
isInputPeerChat,
|
||||||
isInputPeerUser,
|
isInputPeerUser,
|
||||||
|
@ -48,15 +47,15 @@ export async function getChatMember(
|
||||||
? []
|
? []
|
||||||
: res.fullChat.participants.participants
|
: res.fullChat.participants.participants
|
||||||
|
|
||||||
const { users } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
for (const m of members) {
|
for (const m of members) {
|
||||||
if (
|
if (
|
||||||
(user._ === 'inputPeerSelf' &&
|
(user._ === 'inputPeerSelf' &&
|
||||||
(users[m.userId] as tl.RawUser).self) ||
|
(peers.user(m.userId) as tl.RawUser).self) ||
|
||||||
(user._ === 'inputPeerUser' && m.userId === user.userId)
|
(user._ === 'inputPeerUser' && m.userId === user.userId)
|
||||||
) {
|
) {
|
||||||
return new ChatMember(this, m, users)
|
return new ChatMember(this, m, peers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,8 +67,8 @@ export async function getChatMember(
|
||||||
participant: user,
|
participant: user,
|
||||||
})
|
})
|
||||||
|
|
||||||
const { users } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
return new ChatMember(this, res.participant, users)
|
return new ChatMember(this, res.participant, peers)
|
||||||
} else throw new MtInvalidPeerTypeError(chatId, 'chat or channel')
|
} else throw new MtInvalidPeerTypeError(chatId, 'chat or channel')
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@ import {
|
||||||
ChatMember,
|
ChatMember,
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
MtInvalidPeerTypeError,
|
MtInvalidPeerTypeError,
|
||||||
|
PeersIndex,
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import {
|
import {
|
||||||
createUsersChatsIndex,
|
|
||||||
isInputPeerChannel,
|
isInputPeerChannel,
|
||||||
isInputPeerChat,
|
isInputPeerChat,
|
||||||
normalizeToInputChannel,
|
normalizeToInputChannel,
|
||||||
|
@ -13,6 +13,7 @@ import {
|
||||||
import { assertTypeIs } from '../../utils/type-assertion'
|
import { assertTypeIs } from '../../utils/type-assertion'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { ArrayWithTotal } from '../../types'
|
import { ArrayWithTotal } from '../../types'
|
||||||
|
import Long from 'long'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a chunk of members of some chat.
|
* Get a chunk of members of some chat.
|
||||||
|
@ -94,9 +95,11 @@ export async function getChatMembers(
|
||||||
if (params.offset) members = members.slice(params.offset)
|
if (params.offset) members = members.slice(params.offset)
|
||||||
if (params.limit) members = members.slice(0, params.limit)
|
if (params.limit) members = members.slice(0, params.limit)
|
||||||
|
|
||||||
const { users } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const ret = members.map((m) => new ChatMember(this, m, users)) as ArrayWithTotal<ChatMember>
|
const ret = members.map(
|
||||||
|
(m) => new ChatMember(this, m, peers)
|
||||||
|
) as ArrayWithTotal<ChatMember>
|
||||||
|
|
||||||
ret.total = ret.length
|
ret.total = ret.length
|
||||||
return ret
|
return ret
|
||||||
|
@ -140,7 +143,7 @@ export async function getChatMembers(
|
||||||
filter,
|
filter,
|
||||||
offset: params.offset ?? 0,
|
offset: params.offset ?? 0,
|
||||||
limit: params.limit ?? 200,
|
limit: params.limit ?? 200,
|
||||||
hash: 0,
|
hash: Long.ZERO,
|
||||||
})
|
})
|
||||||
|
|
||||||
assertTypeIs(
|
assertTypeIs(
|
||||||
|
@ -149,9 +152,11 @@ export async function getChatMembers(
|
||||||
'channels.channelParticipants'
|
'channels.channelParticipants'
|
||||||
)
|
)
|
||||||
|
|
||||||
const { users } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const ret = res.participants.map((i) => new ChatMember(this, i, users)) as ArrayWithTotal<ChatMember>
|
const ret = res.participants.map(
|
||||||
|
(i) => new ChatMember(this, i, peers)
|
||||||
|
) as ArrayWithTotal<ChatMember>
|
||||||
ret.total = res.count
|
ret.total = res.count
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { Chat, MtTypeAssertionError } from '../../types'
|
import { Chat } from '../../types'
|
||||||
import { assertTypeIs } from '../../utils/type-assertion'
|
import { assertTypeIs } from '../../utils/type-assertion'
|
||||||
import { getMarkedPeerId } from '@mtcute/core'
|
import { getMarkedPeerId } from '@mtcute/core'
|
||||||
import { tl } from 'packages/tl'
|
import { tl } from 'packages/tl'
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import {
|
import { Chat, InputPeerLike, MtNotFoundError } from '../../types'
|
||||||
Chat,
|
|
||||||
InputPeerLike,
|
|
||||||
MtNotFoundError,
|
|
||||||
MtTypeAssertionError,
|
|
||||||
} from '../../types'
|
|
||||||
import {
|
import {
|
||||||
INVITE_LINK_REGEX,
|
INVITE_LINK_REGEX,
|
||||||
normalizeToInputChannel,
|
normalizeToInputChannel,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { Chat, InputPeerLike, MtTypeAssertionError } from '../../types'
|
import { Chat, InputPeerLike } from '../../types'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,9 @@ import { TelegramClient } from '../../client'
|
||||||
import {
|
import {
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
MtInvalidPeerTypeError,
|
MtInvalidPeerTypeError,
|
||||||
MtTypeAssertionError,
|
|
||||||
User,
|
User,
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import { normalizeToInputUser } from '../../utils/peer-utils'
|
import { normalizeToInputUser } from '../../utils/peer-utils'
|
||||||
import { tl } from '@mtcute/tl'
|
|
||||||
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,11 +3,9 @@ import { MaybeArray } from '@mtcute/core'
|
||||||
import {
|
import {
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
MtInvalidPeerTypeError,
|
MtInvalidPeerTypeError,
|
||||||
MtTypeAssertionError,
|
|
||||||
User,
|
User,
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import { normalizeToInputUser } from '../../utils/peer-utils'
|
import { normalizeToInputUser } from '../../utils/peer-utils'
|
||||||
import { tl } from '@mtcute/tl'
|
|
||||||
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { User } from '../../types'
|
import { User } from '../../types'
|
||||||
import { assertTypeIs } from '../../utils/type-assertion'
|
import { assertTypeIs } from '../../utils/type-assertion'
|
||||||
import { tl } from '@mtcute/tl'
|
import Long from 'long'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get list of contacts from your Telegram contacts list.
|
* Get list of contacts from your Telegram contacts list.
|
||||||
|
@ -10,7 +10,7 @@ import { tl } from '@mtcute/tl'
|
||||||
export async function getContacts(this: TelegramClient): Promise<User[]> {
|
export async function getContacts(this: TelegramClient): Promise<User[]> {
|
||||||
const res = await this.call({
|
const res = await this.call({
|
||||||
_: 'contacts.getContacts',
|
_: 'contacts.getContacts',
|
||||||
hash: 0,
|
hash: Long.ZERO,
|
||||||
})
|
})
|
||||||
assertTypeIs('getContacts', res, 'contacts.contacts')
|
assertTypeIs('getContacts', res, 'contacts.contacts')
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { PartialOnly } from '@mtcute/core'
|
import { PartialOnly } from '@mtcute/core'
|
||||||
import bigInt from 'big-integer'
|
import Long from 'long'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Import contacts to your Telegram contacts list.
|
* Import contacts to your Telegram contacts list.
|
||||||
|
@ -13,11 +13,11 @@ export async function importContacts(
|
||||||
this: TelegramClient,
|
this: TelegramClient,
|
||||||
contacts: PartialOnly<Omit<tl.RawInputPhoneContact, '_'>, 'clientId'>[]
|
contacts: PartialOnly<Omit<tl.RawInputPhoneContact, '_'>, 'clientId'>[]
|
||||||
): Promise<tl.contacts.RawImportedContacts> {
|
): Promise<tl.contacts.RawImportedContacts> {
|
||||||
let seq = bigInt.zero
|
let seq = Long.ZERO
|
||||||
|
|
||||||
const contactsNorm: tl.RawInputPhoneContact[] = contacts.map((input) => ({
|
const contactsNorm: tl.RawInputPhoneContact[] = contacts.map((input) => ({
|
||||||
_: 'inputPhoneContact',
|
_: 'inputPhoneContact',
|
||||||
clientId: (seq = seq.plus(1)),
|
clientId: (seq = seq.add(1)),
|
||||||
...input,
|
...input,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,10 @@ import { TelegramClient } from '../../client'
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
MtArgumentError,
|
MtArgumentError,
|
||||||
MtTypeAssertionError,
|
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import { normalizeDate } from '../../utils/misc-utils'
|
import { normalizeDate } from '../../utils/misc-utils'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { getMarkedPeerId } from '@mtcute/core'
|
import Long from 'long'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterate over dialogs.
|
* Iterate over dialogs.
|
||||||
|
@ -241,7 +239,7 @@ export async function* getDialogs(
|
||||||
offsetPeer,
|
offsetPeer,
|
||||||
|
|
||||||
limit: chunkSize,
|
limit: chunkSize,
|
||||||
hash: 0,
|
hash: Long.ZERO,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
if (!dialogs.length) return
|
if (!dialogs.length) return
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { Dialog, MtTypeAssertionError } from '../../types'
|
import { Dialog, MtTypeAssertionError, PeersIndex } from '../../types'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
import { getMarkedPeerId } from '@mtcute/core'
|
import { getMarkedPeerId } from '@mtcute/core'
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
|
@ -16,7 +15,7 @@ export function _parseDialogs(
|
||||||
'messages.dialogsNotModified'
|
'messages.dialogsNotModified'
|
||||||
)
|
)
|
||||||
|
|
||||||
const { users, chats } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const messages: Record<number, tl.TypeMessage> = {}
|
const messages: Record<number, tl.TypeMessage> = {}
|
||||||
res.messages.forEach((msg) => {
|
res.messages.forEach((msg) => {
|
||||||
|
@ -27,7 +26,5 @@ export function _parseDialogs(
|
||||||
|
|
||||||
return res.dialogs
|
return res.dialogs
|
||||||
.filter((it) => it._ === 'dialog')
|
.filter((it) => it._ === 'dialog')
|
||||||
.map(
|
.map((it) => new Dialog(this, it as tl.RawDialog, peers, messages))
|
||||||
(it) => new Dialog(this, it as tl.RawDialog, users, chats, messages)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { TelegramConnection } from '@mtcute/core'
|
import { SessionConnection } from '@mtcute/core'
|
||||||
|
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
|
|
||||||
// @extension
|
// @extension
|
||||||
interface FilesExtension {
|
interface FilesExtension {
|
||||||
_downloadConnections: Record<number, TelegramConnection>
|
_downloadConnections: Record<number, SessionConnection>
|
||||||
}
|
}
|
||||||
|
|
||||||
// @initialize
|
// @initialize
|
||||||
|
|
|
@ -2,7 +2,6 @@ import { TelegramClient } from '../../client'
|
||||||
import {
|
import {
|
||||||
InputMediaLike,
|
InputMediaLike,
|
||||||
isUploadedFile,
|
isUploadedFile,
|
||||||
MtArgumentError,
|
|
||||||
UploadFileLike,
|
UploadFileLike,
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
|
@ -14,9 +13,9 @@ import {
|
||||||
} from '@mtcute/file-id'
|
} from '@mtcute/file-id'
|
||||||
import { extractFileName } from '../../utils/file-utils'
|
import { extractFileName } from '../../utils/file-utils'
|
||||||
import { assertTypeIs } from '../../utils/type-assertion'
|
import { assertTypeIs } from '../../utils/type-assertion'
|
||||||
import bigInt from 'big-integer'
|
|
||||||
import { normalizeDate } from '../../utils/misc-utils'
|
import { normalizeDate } from '../../utils/misc-utils'
|
||||||
import { encodeWaveform } from '../../utils/voice-utils'
|
import { encodeWaveform } from '../../utils/voice-utils'
|
||||||
|
import Long from 'long'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize an {@link InputMediaLike} to `InputMedia`,
|
* Normalize an {@link InputMediaLike} to `InputMedia`,
|
||||||
|
@ -182,7 +181,7 @@ export async function _normalizeInputMedia(
|
||||||
poll: {
|
poll: {
|
||||||
_: 'poll',
|
_: 'poll',
|
||||||
closed: media.closed,
|
closed: media.closed,
|
||||||
id: bigInt.zero,
|
id: Long.ZERO,
|
||||||
publicVoters: media.public,
|
publicVoters: media.public,
|
||||||
multipleChoice: media.multiple,
|
multipleChoice: media.multiple,
|
||||||
quiz: media.type === 'quiz',
|
quiz: media.type === 'quiz',
|
||||||
|
|
|
@ -7,11 +7,11 @@ import {
|
||||||
import type { ReadStream } from 'fs'
|
import type { ReadStream } from 'fs'
|
||||||
import { Readable } from 'stream'
|
import { Readable } from 'stream'
|
||||||
import { determinePartSize, isProbablyPlainText } from '../../utils/file-utils'
|
import { determinePartSize, isProbablyPlainText } from '../../utils/file-utils'
|
||||||
import { randomUlong } from '../../utils/misc-utils'
|
|
||||||
import { fromBuffer } from 'file-type'
|
import { fromBuffer } from 'file-type'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { MtArgumentError, UploadFileLike, UploadedFile } from '../../types'
|
import { MtArgumentError, UploadFileLike, UploadedFile } from '../../types'
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
|
import { randomLong } from '@mtcute/core'
|
||||||
|
|
||||||
let fs: any = null
|
let fs: any = null
|
||||||
let path: any = null
|
let path: any = null
|
||||||
|
@ -200,7 +200,7 @@ export async function uploadFile(
|
||||||
const hash = this._crypto.createMd5()
|
const hash = this._crypto.createMd5()
|
||||||
|
|
||||||
const partCount = ~~((fileSize + partSize - 1) / partSize)
|
const partCount = ~~((fileSize + partSize - 1) / partSize)
|
||||||
this._baseLog.debug(
|
this.log.debug(
|
||||||
'uploading %d bytes file in %d chunks, each %d bytes',
|
'uploading %d bytes file in %d chunks, each %d bytes',
|
||||||
fileSize,
|
fileSize,
|
||||||
partCount,
|
partCount,
|
||||||
|
@ -209,7 +209,7 @@ export async function uploadFile(
|
||||||
|
|
||||||
// why is the file id generated by the client?
|
// why is the file id generated by the client?
|
||||||
// isn't the server supposed to generate it and handle collisions?
|
// isn't the server supposed to generate it and handle collisions?
|
||||||
const fileId = randomUlong()
|
const fileId = randomLong()
|
||||||
let pos = 0
|
let pos = 0
|
||||||
|
|
||||||
for (let idx = 0; idx < partCount; idx++) {
|
for (let idx = 0; idx < partCount; idx++) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { ChatInviteLink, InputPeerLike } from '../../types'
|
import { ChatInviteLink, InputPeerLike, PeersIndex } from '../../types'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
import { normalizeDate } from '../../utils/misc-utils'
|
import { normalizeDate } from '../../utils/misc-utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,7 +42,7 @@ export async function editInviteLink(
|
||||||
usageLimit: params.usageLimit,
|
usageLimit: params.usageLimit,
|
||||||
})
|
})
|
||||||
|
|
||||||
const { users } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
return new ChatInviteLink(this, res.invite, users)
|
return new ChatInviteLink(this, res.invite, peers)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { ChatInviteLink, InputPeerLike, User } from '../../types'
|
import { ChatInviteLink, InputPeerLike, PeersIndex, User } from '../../types'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,18 +39,18 @@ export async function* getInviteLinkMembers(
|
||||||
|
|
||||||
if (!res.importers.length) break
|
if (!res.importers.length) break
|
||||||
|
|
||||||
const { users } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const last = res.importers[res.importers.length - 1]
|
const last = res.importers[res.importers.length - 1]
|
||||||
offsetDate = last.date
|
offsetDate = last.date
|
||||||
offsetUser = {
|
offsetUser = {
|
||||||
_: 'inputUser',
|
_: 'inputUser',
|
||||||
userId: last.userId,
|
userId: last.userId,
|
||||||
accessHash: (users[last.userId] as tl.RawUser).accessHash!,
|
accessHash: (peers.user(last.userId) as tl.RawUser).accessHash!,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const it of res.importers) {
|
for (const it of res.importers) {
|
||||||
const user = new User(this, users[it.userId])
|
const user = new User(this, peers.user(it.userId))
|
||||||
|
|
||||||
yield {
|
yield {
|
||||||
user,
|
user,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { ChatInviteLink, InputPeerLike } from '../../types'
|
import { ChatInviteLink, InputPeerLike, PeersIndex } from '../../types'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get detailed information about an invite link
|
* Get detailed information about an invite link
|
||||||
|
@ -20,7 +19,7 @@ export async function getInviteLink(
|
||||||
link,
|
link,
|
||||||
})
|
})
|
||||||
|
|
||||||
const { users } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
return new ChatInviteLink(this, res.invite, users)
|
return new ChatInviteLink(this, res.invite, peers)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,9 @@ import {
|
||||||
ChatInviteLink,
|
ChatInviteLink,
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
MtInvalidPeerTypeError,
|
MtInvalidPeerTypeError,
|
||||||
|
PeersIndex,
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import {
|
import { normalizeToInputUser } from '../../utils/peer-utils'
|
||||||
createUsersChatsIndex,
|
|
||||||
normalizeToInputUser,
|
|
||||||
} from '../../utils/peer-utils'
|
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,14 +72,14 @@ export async function* getInviteLinks(
|
||||||
|
|
||||||
if (!res.invites.length) break
|
if (!res.invites.length) break
|
||||||
|
|
||||||
const { users } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const last = res.invites[res.invites.length - 1]
|
const last = res.invites[res.invites.length - 1]
|
||||||
offsetDate = last.date
|
offsetDate = last.date
|
||||||
offsetLink = last.link
|
offsetLink = last.link
|
||||||
|
|
||||||
for (const it of res.invites) {
|
for (const it of res.invites) {
|
||||||
yield new ChatInviteLink(this, it, users)
|
yield new ChatInviteLink(this, it, peers)
|
||||||
}
|
}
|
||||||
|
|
||||||
current += res.invites.length
|
current += res.invites.length
|
||||||
|
|
|
@ -2,9 +2,8 @@ import { TelegramClient } from '../../client'
|
||||||
import {
|
import {
|
||||||
ChatInviteLink,
|
ChatInviteLink,
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
MtTypeAssertionError,
|
MtTypeAssertionError, PeersIndex,
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get primary invite link of a chat
|
* Get primary invite link of a chat
|
||||||
|
@ -31,7 +30,7 @@ export async function getPrimaryInviteLink(
|
||||||
'false'
|
'false'
|
||||||
)
|
)
|
||||||
|
|
||||||
const { users } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
return new ChatInviteLink(this, res.invites[0], users)
|
return new ChatInviteLink(this, res.invites[0], peers)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { ChatInviteLink, InputPeerLike } from '../../types'
|
import { ChatInviteLink, InputPeerLike, PeersIndex } from '../../types'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Revoke an invite link.
|
* Revoke an invite link.
|
||||||
|
@ -25,12 +24,12 @@ export async function revokeInviteLink(
|
||||||
revoked: true,
|
revoked: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const { users } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const invite =
|
const invite =
|
||||||
res._ === 'messages.exportedChatInviteReplaced'
|
res._ === 'messages.exportedChatInviteReplaced'
|
||||||
? res.newInvite
|
? res.newInvite
|
||||||
: res.invite
|
: res.invite
|
||||||
|
|
||||||
return new ChatInviteLink(this, invite, users)
|
return new ChatInviteLink(this, invite, peers)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { InputPeerLike, MtTypeAssertionError, Poll } from '../../types'
|
import { InputPeerLike, MtTypeAssertionError, PeersIndex, Poll } from '../../types'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
import bigInt from 'big-integer'
|
|
||||||
import { assertTypeIs } from '../../utils/type-assertion'
|
import { assertTypeIs } from '../../utils/type-assertion'
|
||||||
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
||||||
|
import Long from 'long'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close a poll sent by you.
|
* Close a poll sent by you.
|
||||||
|
@ -28,7 +27,7 @@ export async function closePoll(
|
||||||
_: 'inputMediaPoll',
|
_: 'inputMediaPoll',
|
||||||
poll: {
|
poll: {
|
||||||
_: 'poll',
|
_: 'poll',
|
||||||
id: bigInt.zero,
|
id: Long.ZERO,
|
||||||
closed: true,
|
closed: true,
|
||||||
question: '',
|
question: '',
|
||||||
answers: [],
|
answers: [],
|
||||||
|
@ -54,7 +53,7 @@ export async function closePoll(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { users } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
return new Poll(this, upd.poll, users, upd.results)
|
return new Poll(this, upd.poll, peers, upd.results)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { InputPeerLike } from '../../types'
|
import { InputPeerLike } from '../../types'
|
||||||
import { MaybeArray } from '@mtcute/core'
|
import { MaybeArray } from '@mtcute/core'
|
||||||
import {
|
|
||||||
isInputPeerChannel,
|
|
||||||
normalizeToInputChannel,
|
|
||||||
} from '../../utils/peer-utils'
|
|
||||||
import { createDummyUpdate } from '../../utils/updates-utils'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete scheduled messages.
|
* Delete scheduled messages.
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { Message, MtTypeAssertionError } from '../../types'
|
import { Message, MtTypeAssertionError, PeersIndex } from '../../types'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
|
@ -24,13 +23,12 @@ export function _findMessageInUpdate(
|
||||||
u._ === 'updateNewChannelMessage' ||
|
u._ === 'updateNewChannelMessage' ||
|
||||||
u._ === 'updateNewScheduledMessage'))
|
u._ === 'updateNewScheduledMessage'))
|
||||||
) {
|
) {
|
||||||
const { users, chats } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
return new Message(
|
return new Message(
|
||||||
this,
|
this,
|
||||||
u.message,
|
u.message,
|
||||||
users,
|
peers,
|
||||||
chats,
|
|
||||||
u._ === 'updateNewScheduledMessage'
|
u._ === 'updateNewScheduledMessage'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,11 @@ import {
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
Message,
|
Message,
|
||||||
MtArgumentError,
|
MtArgumentError,
|
||||||
MtTypeAssertionError,
|
PeersIndex,
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import { MaybeArray } from '@mtcute/core'
|
import { MaybeArray, randomLong } from '@mtcute/core'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
import { normalizeDate } from '../../utils/misc-utils'
|
||||||
import { normalizeDate, randomUlong } from '../../utils/misc-utils'
|
|
||||||
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -234,7 +233,7 @@ export async function forwardMessages(
|
||||||
silent: params.silent,
|
silent: params.silent,
|
||||||
scheduleDate: normalizeDate(params.schedule),
|
scheduleDate: normalizeDate(params.schedule),
|
||||||
randomId: [...Array((messages as number[]).length)].map(() =>
|
randomId: [...Array((messages as number[]).length)].map(() =>
|
||||||
randomUlong()
|
randomLong()
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -242,7 +241,7 @@ export async function forwardMessages(
|
||||||
|
|
||||||
this._handleUpdate(res, true)
|
this._handleUpdate(res, true)
|
||||||
|
|
||||||
const { users, chats } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const forwarded: Message[] = []
|
const forwarded: Message[] = []
|
||||||
res.updates.forEach((upd) => {
|
res.updates.forEach((upd) => {
|
||||||
|
@ -250,7 +249,14 @@ export async function forwardMessages(
|
||||||
case 'updateNewMessage':
|
case 'updateNewMessage':
|
||||||
case 'updateNewChannelMessage':
|
case 'updateNewChannelMessage':
|
||||||
case 'updateNewScheduledMessage':
|
case 'updateNewScheduledMessage':
|
||||||
forwarded.push(new Message(this, upd.message, users, chats))
|
forwarded.push(
|
||||||
|
new Message(
|
||||||
|
this,
|
||||||
|
upd.message,
|
||||||
|
peers,
|
||||||
|
upd._ === 'updateNewScheduledMessage'
|
||||||
|
)
|
||||||
|
)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { InputPeerLike, Message } from '../../types'
|
import { InputPeerLike, Message, PeersIndex } from '../../types'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
export async function _getDiscussionMessage(
|
export async function _getDiscussionMessage(
|
||||||
|
@ -71,7 +70,7 @@ export async function getDiscussionMessage(
|
||||||
return null
|
return null
|
||||||
|
|
||||||
const msg = res.messages[0]
|
const msg = res.messages[0]
|
||||||
const { users, chats } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
return new Message(this, msg, users, chats)
|
return new Message(this, msg, peers)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { InputPeerLike, Message, MtTypeAssertionError } from '../../types'
|
import { InputPeerLike, Message, MtTypeAssertionError, PeersIndex } from '../../types'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
import { normalizeDate } from '../../utils/misc-utils'
|
import { normalizeDate } from '../../utils/misc-utils'
|
||||||
|
import Long from 'long'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a chunk of the chat history.
|
* Retrieve a chunk of the chat history.
|
||||||
|
@ -70,7 +70,7 @@ export async function getHistory(
|
||||||
limit,
|
limit,
|
||||||
maxId: 0,
|
maxId: 0,
|
||||||
minId: 0,
|
minId: 0,
|
||||||
hash: 0,
|
hash: Long.ZERO,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (res._ === 'messages.messagesNotModified')
|
if (res._ === 'messages.messagesNotModified')
|
||||||
|
@ -80,11 +80,11 @@ export async function getHistory(
|
||||||
res._
|
res._
|
||||||
)
|
)
|
||||||
|
|
||||||
const { users, chats } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const msgs = res.messages
|
const msgs = res.messages
|
||||||
.filter((msg) => msg._ !== 'messageEmpty')
|
.filter((msg) => msg._ !== 'messageEmpty')
|
||||||
.map((msg) => new Message(this, msg, users, chats))
|
.map((msg) => new Message(this, msg, peers))
|
||||||
|
|
||||||
if (params.reverse) msgs.reverse()
|
if (params.reverse) msgs.reverse()
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { MaybeArray } from '@mtcute/core'
|
import { MaybeArray } from '@mtcute/core'
|
||||||
import {
|
|
||||||
createUsersChatsIndex,
|
|
||||||
} from '../../utils/peer-utils'
|
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { Message, MtTypeAssertionError } from '../../types'
|
import { Message, MtTypeAssertionError, PeersIndex } from '../../types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a single message from PM or legacy group by its ID.
|
* Get a single message from PM or legacy group by its ID.
|
||||||
|
@ -73,14 +70,13 @@ export async function getMessagesUnsafe(
|
||||||
res._
|
res._
|
||||||
)
|
)
|
||||||
|
|
||||||
const { users, chats } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const ret = res.messages
|
const ret = res.messages.map((msg) => {
|
||||||
.map((msg) => {
|
if (msg._ === 'messageEmpty') return null
|
||||||
if (msg._ === 'messageEmpty') return null
|
|
||||||
|
|
||||||
return new Message(this, msg, users, chats)
|
return new Message(this, msg, peers)
|
||||||
})
|
})
|
||||||
|
|
||||||
return isSingle ? ret[0] : ret
|
return isSingle ? ret[0] : ret
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { MaybeArray } from '@mtcute/core'
|
import { MaybeArray } from '@mtcute/core'
|
||||||
import {
|
import {
|
||||||
createUsersChatsIndex,
|
|
||||||
isInputPeerChannel,
|
isInputPeerChannel,
|
||||||
normalizeToInputChannel,
|
normalizeToInputChannel,
|
||||||
} from '../../utils/peer-utils'
|
} from '../../utils/peer-utils'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { Message, InputPeerLike, MtTypeAssertionError } from '../../types'
|
import { Message, InputPeerLike, MtTypeAssertionError, PeersIndex } from '../../types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a single message in chat by its ID
|
* Get a single message in chat by its ID
|
||||||
|
@ -84,7 +83,7 @@ export async function getMessages(
|
||||||
res._
|
res._
|
||||||
)
|
)
|
||||||
|
|
||||||
const { users, chats } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const ret = res.messages.map((msg) => {
|
const ret = res.messages.map((msg) => {
|
||||||
if (msg._ === 'messageEmpty') return null
|
if (msg._ === 'messageEmpty') return null
|
||||||
|
@ -109,7 +108,7 @@ export async function getMessages(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Message(this, msg, users, chats)
|
return new Message(this, msg, peers)
|
||||||
})
|
})
|
||||||
|
|
||||||
return isSingle ? ret[0] : ret
|
return isSingle ? ret[0] : ret
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { MaybeArray } from '@mtcute/core'
|
import { MaybeArray } from '@mtcute/core'
|
||||||
import {
|
import {
|
||||||
createUsersChatsIndex,
|
Message,
|
||||||
isInputPeerChannel,
|
InputPeerLike,
|
||||||
normalizeToInputChannel,
|
MtTypeAssertionError,
|
||||||
} from '../../utils/peer-utils'
|
PeersIndex,
|
||||||
import { tl } from '@mtcute/tl'
|
} from '../../types'
|
||||||
import { Message, InputPeerLike, MtTypeAssertionError } from '../../types'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a single scheduled message in chat by its ID
|
* Get a single scheduled message in chat by its ID
|
||||||
|
@ -60,12 +59,12 @@ export async function getScheduledMessages(
|
||||||
res._
|
res._
|
||||||
)
|
)
|
||||||
|
|
||||||
const { users, chats } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const ret = res.messages.map((msg) => {
|
const ret = res.messages.map((msg) => {
|
||||||
if (msg._ === 'messageEmpty') return null
|
if (msg._ === 'messageEmpty') return null
|
||||||
|
|
||||||
return new Message(this, msg, users, chats)
|
return new Message(this, msg, peers, true)
|
||||||
})
|
})
|
||||||
|
|
||||||
return isSingle ? ret[0] : ret
|
return isSingle ? ret[0] : ret
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { TelegramConnection } from '@mtcute/core'
|
import { SessionConnection } from '@mtcute/core'
|
||||||
import { parseInlineMessageId } from '../../utils/inline-utils'
|
import { parseInlineMessageId } from '../../utils/inline-utils'
|
||||||
|
|
||||||
// @extension
|
// @extension
|
||||||
interface InlineExtension {
|
interface InlineExtension {
|
||||||
_connectionsForInline: Record<number, TelegramConnection>
|
_connectionsForInline: Record<number, SessionConnection>
|
||||||
}
|
}
|
||||||
|
|
||||||
// @initialize
|
// @initialize
|
||||||
|
@ -17,7 +17,7 @@ function _initializeInline(this: TelegramClient) {
|
||||||
export async function _normalizeInline(
|
export async function _normalizeInline(
|
||||||
this: TelegramClient,
|
this: TelegramClient,
|
||||||
id: string | tl.TypeInputBotInlineMessageID
|
id: string | tl.TypeInputBotInlineMessageID
|
||||||
): Promise<[tl.TypeInputBotInlineMessageID, TelegramConnection]> {
|
): Promise<[tl.TypeInputBotInlineMessageID, SessionConnection]> {
|
||||||
if (typeof id === 'string') {
|
if (typeof id === 'string') {
|
||||||
id = parseInlineMessageId(id)
|
id = parseInlineMessageId(id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { Message, MtTypeAssertionError } from '../../types'
|
import { Message, MtTypeAssertionError, PeersIndex } from '../../types'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
import { SearchFilters } from '../../types'
|
import { SearchFilters } from '../../types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,11 +76,11 @@ export async function* searchGlobal(
|
||||||
res._
|
res._
|
||||||
)
|
)
|
||||||
|
|
||||||
const { users, chats } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const msgs = res.messages
|
const msgs = res.messages
|
||||||
.filter((msg) => msg._ !== 'messageEmpty')
|
.filter((msg) => msg._ !== 'messageEmpty')
|
||||||
.map((msg) => new Message(this, msg, users, chats))
|
.map((msg) => new Message(this, msg, peers))
|
||||||
|
|
||||||
if (!msgs.length) break
|
if (!msgs.length) break
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { InputPeerLike, Message, MtTypeAssertionError } from '../../types'
|
import { InputPeerLike, Message, MtTypeAssertionError, PeersIndex } from '../../types'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
import { SearchFilters } from '../../types'
|
import { SearchFilters } from '../../types'
|
||||||
|
import Long from 'long'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for messages inside a specific chat
|
* Search for messages inside a specific chat
|
||||||
|
@ -88,7 +88,7 @@ export async function* searchMessages(
|
||||||
minId: 0,
|
minId: 0,
|
||||||
maxId: 0,
|
maxId: 0,
|
||||||
fromId: fromUser,
|
fromId: fromUser,
|
||||||
hash: 0,
|
hash: Long.ZERO,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (res._ === 'messages.messagesNotModified')
|
if (res._ === 'messages.messagesNotModified')
|
||||||
|
@ -98,11 +98,11 @@ export async function* searchMessages(
|
||||||
res._
|
res._
|
||||||
)
|
)
|
||||||
|
|
||||||
const { users, chats } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const msgs = res.messages
|
const msgs = res.messages
|
||||||
.filter((msg) => msg._ !== 'messageEmpty')
|
.filter((msg) => msg._ !== 'messageEmpty')
|
||||||
.map((msg) => new Message(this, msg, users, chats))
|
.map((msg) => new Message(this, msg, peers))
|
||||||
|
|
||||||
if (!msgs.length) break
|
if (!msgs.length) break
|
||||||
|
|
||||||
|
|
|
@ -3,18 +3,17 @@ import {
|
||||||
BotKeyboard, InputFileLike,
|
BotKeyboard, InputFileLike,
|
||||||
InputMediaLike,
|
InputMediaLike,
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
Message, MtArgumentError,
|
Message, MtArgumentError, PeersIndex,
|
||||||
ReplyMarkup,
|
ReplyMarkup,
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import {
|
import {
|
||||||
normalizeDate,
|
normalizeDate,
|
||||||
normalizeMessageId,
|
normalizeMessageId,
|
||||||
randomUlong,
|
|
||||||
} from '../../utils/misc-utils'
|
} 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 { MessageNotFoundError } from '@mtcute/tl/errors'
|
import { MessageNotFoundError } from '@mtcute/tl/errors'
|
||||||
|
import { randomLong } from '@mtcute/core'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a group of media.
|
* Send a group of media.
|
||||||
|
@ -165,7 +164,7 @@ export async function sendMediaGroup(
|
||||||
|
|
||||||
multiMedia.push({
|
multiMedia.push({
|
||||||
_: 'inputSingleMedia',
|
_: 'inputSingleMedia',
|
||||||
randomId: randomUlong(),
|
randomId: randomLong(),
|
||||||
media: inputMedia,
|
media: inputMedia,
|
||||||
message,
|
message,
|
||||||
entities,
|
entities,
|
||||||
|
@ -178,7 +177,7 @@ export async function sendMediaGroup(
|
||||||
multiMedia,
|
multiMedia,
|
||||||
silent: params.silent,
|
silent: params.silent,
|
||||||
replyToMsgId: replyTo,
|
replyToMsgId: replyTo,
|
||||||
randomId: randomUlong(),
|
randomId: randomLong(),
|
||||||
scheduleDate: normalizeDate(params.schedule),
|
scheduleDate: normalizeDate(params.schedule),
|
||||||
replyMarkup,
|
replyMarkup,
|
||||||
clearDraft: params.clearDraft,
|
clearDraft: params.clearDraft,
|
||||||
|
@ -187,7 +186,7 @@ export async function sendMediaGroup(
|
||||||
assertIsUpdatesGroup('_findMessageInUpdate', res)
|
assertIsUpdatesGroup('_findMessageInUpdate', res)
|
||||||
this._handleUpdate(res, true)
|
this._handleUpdate(res, true)
|
||||||
|
|
||||||
const { users, chats } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const msgs = res.updates
|
const msgs = res.updates
|
||||||
.filter(
|
.filter(
|
||||||
|
@ -201,8 +200,7 @@ export async function sendMediaGroup(
|
||||||
new Message(
|
new Message(
|
||||||
this,
|
this,
|
||||||
(u as any).message,
|
(u as any).message,
|
||||||
users,
|
peers,
|
||||||
chats,
|
|
||||||
u._ === 'updateNewScheduledMessage'
|
u._ === 'updateNewScheduledMessage'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import {
|
import {
|
||||||
BotKeyboard, FormattedString,
|
BotKeyboard,
|
||||||
|
FormattedString,
|
||||||
InputMediaLike,
|
InputMediaLike,
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
Message, MtArgumentError,
|
Message,
|
||||||
|
MtArgumentError,
|
||||||
ReplyMarkup,
|
ReplyMarkup,
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import {
|
import { normalizeDate, normalizeMessageId } from '../../utils/misc-utils'
|
||||||
normalizeDate,
|
|
||||||
normalizeMessageId,
|
|
||||||
randomUlong,
|
|
||||||
} from '../../utils/misc-utils'
|
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { MessageNotFoundError } from '@mtcute/tl/errors'
|
import { MessageNotFoundError } from '@mtcute/tl/errors'
|
||||||
|
import { randomLong } from '@mtcute/core'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a single media (a photo or a document-based media)
|
* Send a single media (a photo or a document-based media)
|
||||||
|
@ -157,8 +156,7 @@ export async function sendMedia(
|
||||||
|
|
||||||
const msg = await this.getMessages(peer, replyTo)
|
const msg = await this.getMessages(peer, replyTo)
|
||||||
|
|
||||||
if (!msg)
|
if (!msg) throw new MessageNotFoundError()
|
||||||
throw new MessageNotFoundError()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await this.call({
|
const res = await this.call({
|
||||||
|
@ -167,7 +165,7 @@ export async function sendMedia(
|
||||||
media: inputMedia,
|
media: inputMedia,
|
||||||
silent: params.silent,
|
silent: params.silent,
|
||||||
replyToMsgId: replyTo,
|
replyToMsgId: replyTo,
|
||||||
randomId: randomUlong(),
|
randomId: randomLong(),
|
||||||
scheduleDate: normalizeDate(params.schedule),
|
scheduleDate: normalizeDate(params.schedule),
|
||||||
replyMarkup,
|
replyMarkup,
|
||||||
message,
|
message,
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { InputPeerLike, Message } from '../../types'
|
import { InputPeerLike, Message, PeersIndex } from '../../types'
|
||||||
import { MaybeArray } from '@mtcute/core'
|
import { MaybeArray } from '@mtcute/core'
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send s previously scheduled message.
|
* Send s previously scheduled message.
|
||||||
|
@ -56,7 +55,7 @@ export async function sendScheduled(
|
||||||
assertIsUpdatesGroup('sendScheduled', res)
|
assertIsUpdatesGroup('sendScheduled', res)
|
||||||
this._handleUpdate(res, true)
|
this._handleUpdate(res, true)
|
||||||
|
|
||||||
const { users, chats } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
const msgs = res.updates
|
const msgs = res.updates
|
||||||
.filter(
|
.filter(
|
||||||
|
@ -69,8 +68,7 @@ export async function sendScheduled(
|
||||||
new Message(
|
new Message(
|
||||||
this,
|
this,
|
||||||
(u as any).message,
|
(u as any).message,
|
||||||
users,
|
peers
|
||||||
chats
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -4,19 +4,16 @@ import { inputPeerToPeer } from '../../utils/peer-utils'
|
||||||
import {
|
import {
|
||||||
normalizeDate,
|
normalizeDate,
|
||||||
normalizeMessageId,
|
normalizeMessageId,
|
||||||
randomUlong,
|
|
||||||
} from '../../utils/misc-utils'
|
} from '../../utils/misc-utils'
|
||||||
import {
|
import {
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
Message,
|
Message,
|
||||||
BotKeyboard,
|
BotKeyboard,
|
||||||
ReplyMarkup,
|
ReplyMarkup,
|
||||||
UsersIndex,
|
|
||||||
MtTypeAssertionError,
|
MtTypeAssertionError,
|
||||||
ChatsIndex,
|
MtArgumentError, FormattedString, PeersIndex,
|
||||||
MtArgumentError, FormattedString,
|
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import { getMarkedPeerId, MessageNotFoundError } from '@mtcute/core'
|
import { getMarkedPeerId, MessageNotFoundError, randomLong } from '@mtcute/core'
|
||||||
import { createDummyUpdate } from '../../utils/updates-utils'
|
import { createDummyUpdate } from '../../utils/updates-utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -143,7 +140,7 @@ export async function sendText(
|
||||||
noWebpage: params.disableWebPreview,
|
noWebpage: params.disableWebPreview,
|
||||||
silent: params.silent,
|
silent: params.silent,
|
||||||
replyToMsgId: replyTo,
|
replyToMsgId: replyTo,
|
||||||
randomId: randomUlong(),
|
randomId: randomLong(),
|
||||||
scheduleDate: normalizeDate(params.schedule),
|
scheduleDate: normalizeDate(params.schedule),
|
||||||
replyMarkup,
|
replyMarkup,
|
||||||
message,
|
message,
|
||||||
|
@ -170,8 +167,7 @@ export async function sendText(
|
||||||
this._date = res.date
|
this._date = res.date
|
||||||
this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount))
|
this._handleUpdate(createDummyUpdate(res.pts, res.ptsCount))
|
||||||
|
|
||||||
const users: UsersIndex = {}
|
const peers = new PeersIndex()
|
||||||
const chats: ChatsIndex = {}
|
|
||||||
|
|
||||||
const fetchPeer = async (
|
const fetchPeer = async (
|
||||||
peer: tl.TypePeer | tl.TypeInputPeer
|
peer: tl.TypePeer | tl.TypeInputPeer
|
||||||
|
@ -206,13 +202,13 @@ export async function sendText(
|
||||||
|
|
||||||
switch (cached._) {
|
switch (cached._) {
|
||||||
case 'user':
|
case 'user':
|
||||||
users[cached.id] = cached
|
peers.users[cached.id] = cached
|
||||||
break
|
break
|
||||||
case 'chat':
|
case 'chat':
|
||||||
case 'chatForbidden':
|
case 'chatForbidden':
|
||||||
case 'channel':
|
case 'channel':
|
||||||
case 'channelForbidden':
|
case 'channelForbidden':
|
||||||
chats[cached.id] = cached
|
peers.chats[cached.id] = cached
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
throw new MtTypeAssertionError(
|
throw new MtTypeAssertionError(
|
||||||
|
@ -226,7 +222,7 @@ export async function sendText(
|
||||||
await fetchPeer(peer)
|
await fetchPeer(peer)
|
||||||
await fetchPeer(msg.fromId!)
|
await fetchPeer(msg.fromId!)
|
||||||
|
|
||||||
const ret = new Message(this, msg, users, chats)
|
const ret = new Message(this, msg, peers)
|
||||||
this._pushConversationMessage(ret)
|
this._pushConversationMessage(ret)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@ import {
|
||||||
InputPeerLike,
|
InputPeerLike,
|
||||||
MtArgumentError,
|
MtArgumentError,
|
||||||
MtTypeAssertionError,
|
MtTypeAssertionError,
|
||||||
|
PeersIndex,
|
||||||
Poll,
|
Poll,
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import { MaybeArray, MessageNotFoundError } from '@mtcute/core'
|
import { MaybeArray, MessageNotFoundError } from '@mtcute/core'
|
||||||
import { createUsersChatsIndex } from '../../utils/peer-utils'
|
|
||||||
import { assertTypeIs } from '../../utils/type-assertion'
|
import { assertTypeIs } from '../../utils/type-assertion'
|
||||||
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
import { assertIsUpdatesGroup } from '../../utils/updates-utils'
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ export async function sendVote(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { users } = createUsersChatsIndex(res)
|
const peers = PeersIndex.from(res)
|
||||||
|
|
||||||
return new Poll(this, upd.poll, users, upd.results)
|
return new Poll(this, upd.poll, peers, upd.results)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { InputFileLike, InputStickerSetItem, StickerSet } from '../../types'
|
import { InputStickerSetItem, StickerSet } from '../../types'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
|
|
||||||
const MASK_POS = {
|
const MASK_POS = {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { StickerSet } from '../../types'
|
import { StickerSet } from '../../types'
|
||||||
import { assertTypeIs } from '../../utils/type-assertion'
|
import { assertTypeIs } from '../../utils/type-assertion'
|
||||||
|
import Long from 'long'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of all installed sticker packs
|
* Get a list of all installed sticker packs
|
||||||
|
@ -17,7 +18,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: Long.ZERO,
|
||||||
})
|
})
|
||||||
|
|
||||||
assertTypeIs('getInstalledStickers', res, 'messages.allStickers')
|
assertTypeIs('getInstalledStickers', res, 'messages.allStickers')
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,6 +2,7 @@ import { InputPeerLike, MtInvalidPeerTypeError } from '../../types'
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { Chat } from '../../types'
|
import { Chat } from '../../types'
|
||||||
import { normalizeToInputUser } from '../../utils/peer-utils'
|
import { normalizeToInputUser } from '../../utils/peer-utils'
|
||||||
|
import Long from 'long'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of common chats you have with a given user
|
* Get a list of common chats you have with a given user
|
||||||
|
|
|
@ -15,9 +15,20 @@ export function getMe(this: TelegramClient): Promise<User> {
|
||||||
_: 'inputUserSelf',
|
_: 'inputUserSelf',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}).then(([user]) => {
|
}).then(async ([user]) => {
|
||||||
assertTypeIs('getMe (@ users.getUsers)', user, 'user')
|
assertTypeIs('getMe (@ users.getUsers)', user, 'user')
|
||||||
|
|
||||||
|
if (this._userId !== user.id) {
|
||||||
|
// there is such possibility, e.g. when
|
||||||
|
// using a string session without `self`,
|
||||||
|
// or logging out and re-logging in
|
||||||
|
// we need to update the fields accordingly,
|
||||||
|
// and force-save the session
|
||||||
|
this._userId = user.id
|
||||||
|
this._isBot = !!user.bot
|
||||||
|
await this._saveStorage()
|
||||||
|
}
|
||||||
|
|
||||||
this._selfUsername = user.username ?? null
|
this._selfUsername = user.username ?? null
|
||||||
|
|
||||||
return new User(this, user)
|
return new User(this, user)
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { User } from '../../types'
|
|
||||||
import { assertTypeIs } from '../../utils/type-assertion'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get currently authorized user's username.
|
* Get currently authorized user's username.
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { InputPeerLike, MtInvalidPeerTypeError, Photo } from '../../types'
|
import { InputPeerLike, MtInvalidPeerTypeError, Photo } from '../../types'
|
||||||
import { normalizeToInputUser } from '../../utils/peer-utils'
|
import { normalizeToInputUser } from '../../utils/peer-utils'
|
||||||
import bigInt from 'big-integer'
|
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
|
import Long from 'long'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of profile pictures of a user
|
* Get a list of profile pictures of a user
|
||||||
|
@ -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: Long.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))
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { InputPeerLike, User } from '../../types'
|
import { InputPeerLike, User } from '../../types'
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { MaybeArray } from '@mtcute/core'
|
import { MaybeArray } from '@mtcute/core'
|
||||||
import { tl } from '@mtcute/tl'
|
|
||||||
import { normalizeToInputUser } from '../../utils/peer-utils'
|
import { normalizeToInputUser } from '../../utils/peer-utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { TelegramClient } from '../../client'
|
||||||
import { InputPeerLike, MtInvalidPeerTypeError, Photo } from '../../types'
|
import { InputPeerLike, MtInvalidPeerTypeError, Photo } 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 bigInt from 'big-integer'
|
import Long from 'long'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterate over profile photos
|
* Iterate over profile photos
|
||||||
|
@ -54,7 +54,7 @@ export async function* iterProfilePhotos(
|
||||||
|
|
||||||
const limit = Math.min(params.chunkSize || 100, total)
|
const limit = Math.min(params.chunkSize || 100, total)
|
||||||
|
|
||||||
const maxId = params.maxId || bigInt.zero
|
const maxId = params.maxId || Long.ZERO
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const res = await this.call({
|
const res = await this.call({
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { InputPeerLike, MtNotFoundError } from '../../types'
|
import { InputPeerLike, MtNotFoundError } from '../../types'
|
||||||
import { getBasicPeerType, getMarkedPeerId, MAX_CHANNEL_ID } from '@mtcute/core'
|
import { getBasicPeerType, getMarkedPeerId, toggleChannelIdMark } from '@mtcute/core'
|
||||||
import bigInt from 'big-integer'
|
|
||||||
import { normalizeToInputPeer } from '../../utils/peer-utils'
|
import { normalizeToInputPeer } from '../../utils/peer-utils'
|
||||||
|
import Long from 'long'
|
||||||
import { assertTypeIs } from '../../utils/type-assertion'
|
import { assertTypeIs } from '../../utils/type-assertion'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,11 +11,13 @@ import { assertTypeIs } from '../../utils/type-assertion'
|
||||||
* Useful when an `InputPeer` is needed.
|
* Useful when an `InputPeer` is needed.
|
||||||
*
|
*
|
||||||
* @param peerId The peer identifier that you want to extract the `InputPeer` from.
|
* @param peerId The peer identifier that you want to extract the `InputPeer` from.
|
||||||
|
* @param force Whether to force re-fetch the peer from the server
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
export async function resolvePeer(
|
export async function resolvePeer(
|
||||||
this: TelegramClient,
|
this: TelegramClient,
|
||||||
peerId: InputPeerLike
|
peerId: InputPeerLike,
|
||||||
|
force = false
|
||||||
): Promise<tl.TypeInputPeer> {
|
): Promise<tl.TypeInputPeer> {
|
||||||
// for convenience we also accept tl objects directly
|
// for convenience we also accept tl objects directly
|
||||||
if (typeof peerId === 'object') {
|
if (typeof peerId === 'object') {
|
||||||
|
@ -26,7 +28,7 @@ export async function resolvePeer(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof peerId === 'number') {
|
if (typeof peerId === 'number' && !force) {
|
||||||
const fromStorage = await this.storage.getPeerById(peerId)
|
const fromStorage = await this.storage.getPeerById(peerId)
|
||||||
if (fromStorage) return fromStorage
|
if (fromStorage) return fromStorage
|
||||||
}
|
}
|
||||||
|
@ -42,7 +44,7 @@ export async function resolvePeer(
|
||||||
|
|
||||||
const res = await this.call({
|
const res = await this.call({
|
||||||
_: 'contacts.getContacts',
|
_: 'contacts.getContacts',
|
||||||
hash: 0,
|
hash: Long.ZERO,
|
||||||
})
|
})
|
||||||
|
|
||||||
assertTypeIs('contacts.getContacts', res, 'contacts.contacts')
|
assertTypeIs('contacts.getContacts', res, 'contacts.contacts')
|
||||||
|
@ -62,8 +64,10 @@ export async function resolvePeer(
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// username
|
// username
|
||||||
const fromStorage = await this.storage.getPeerByUsername(peerId)
|
if (!force) {
|
||||||
if (fromStorage) return fromStorage
|
const fromStorage = await this.storage.getPeerByUsername(peerId)
|
||||||
|
if (fromStorage) return fromStorage
|
||||||
|
}
|
||||||
|
|
||||||
const res = await this.call({
|
const res = await this.call({
|
||||||
_: 'contacts.resolveUsername',
|
_: 'contacts.resolveUsername',
|
||||||
|
@ -122,7 +126,7 @@ export async function resolvePeer(
|
||||||
{
|
{
|
||||||
_: 'inputUser',
|
_: 'inputUser',
|
||||||
userId: peerId,
|
userId: peerId,
|
||||||
accessHash: bigInt.zero,
|
accessHash: Long.ZERO,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
@ -159,14 +163,15 @@ export async function resolvePeer(
|
||||||
// break
|
// break
|
||||||
}
|
}
|
||||||
case 'channel': {
|
case 'channel': {
|
||||||
const id = MAX_CHANNEL_ID - peerId
|
const id = toggleChannelIdMark(peerId as number)
|
||||||
|
|
||||||
const res = await this.call({
|
const res = await this.call({
|
||||||
_: 'channels.getChannels',
|
_: 'channels.getChannels',
|
||||||
id: [
|
id: [
|
||||||
{
|
{
|
||||||
_: 'inputChannel',
|
_: 'inputChannel',
|
||||||
channelId: MAX_CHANNEL_ID - peerId,
|
channelId: id,
|
||||||
accessHash: bigInt.zero,
|
accessHash: Long.ZERO,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { Message } from '../messages'
|
||||||
import { MtArgumentError } from '../errors'
|
import { MtArgumentError } from '../errors'
|
||||||
import { BasicPeerType, getBasicPeerType, getMarkedPeerId } from '@mtcute/core'
|
import { BasicPeerType, getBasicPeerType, getMarkedPeerId } from '@mtcute/core'
|
||||||
import { encodeInlineMessageId } from '../../utils/inline-utils'
|
import { encodeInlineMessageId } from '../../utils/inline-utils'
|
||||||
import { User, UsersIndex } from '../peers'
|
import { User, PeersIndex } from '../peers'
|
||||||
import { MessageNotFoundError } from '@mtcute/core'
|
import { MessageNotFoundError } from '@mtcute/core'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,22 +13,13 @@ import { MessageNotFoundError } from '@mtcute/core'
|
||||||
* of an inline keyboard.
|
* of an inline keyboard.
|
||||||
*/
|
*/
|
||||||
export class CallbackQuery {
|
export class CallbackQuery {
|
||||||
readonly client: TelegramClient
|
|
||||||
readonly raw:
|
|
||||||
| tl.RawUpdateBotCallbackQuery
|
|
||||||
| tl.RawUpdateInlineBotCallbackQuery
|
|
||||||
|
|
||||||
readonly _users: UsersIndex
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
readonly client: TelegramClient,
|
||||||
raw: tl.RawUpdateBotCallbackQuery | tl.RawUpdateInlineBotCallbackQuery,
|
readonly raw:
|
||||||
users: UsersIndex
|
| tl.RawUpdateBotCallbackQuery
|
||||||
) {
|
| tl.RawUpdateInlineBotCallbackQuery,
|
||||||
this.client = client
|
readonly _peers: PeersIndex
|
||||||
this.raw = raw
|
) {}
|
||||||
this._users = users
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID of this callback query
|
* ID of this callback query
|
||||||
|
@ -43,7 +34,10 @@ export class CallbackQuery {
|
||||||
*/
|
*/
|
||||||
get user(): User {
|
get user(): User {
|
||||||
if (!this._user) {
|
if (!this._user) {
|
||||||
this._user = new User(this.client, this._users[this.raw.userId])
|
this._user = new User(
|
||||||
|
this.client,
|
||||||
|
this._peers.user(this.raw.userId)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._user
|
return this._user
|
||||||
|
|
|
@ -1,26 +1,17 @@
|
||||||
import { makeInspectable } from '../utils'
|
import { makeInspectable } from '../utils'
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { User, UsersIndex } from '../peers'
|
import { PeersIndex, User } from '../peers'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Game high score
|
* Game high score
|
||||||
*/
|
*/
|
||||||
export class GameHighScore {
|
export class GameHighScore {
|
||||||
readonly client: TelegramClient
|
|
||||||
readonly raw: tl.RawHighScore
|
|
||||||
|
|
||||||
readonly _users: UsersIndex
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
readonly client: TelegramClient,
|
||||||
raw: tl.RawHighScore,
|
readonly raw: tl.RawHighScore,
|
||||||
users: UsersIndex
|
readonly _peers: PeersIndex
|
||||||
) {
|
) {}
|
||||||
this.client = client
|
|
||||||
this.raw = raw
|
|
||||||
this._users = users
|
|
||||||
}
|
|
||||||
|
|
||||||
private _user?: User
|
private _user?: User
|
||||||
/**
|
/**
|
||||||
|
@ -28,7 +19,10 @@ export class GameHighScore {
|
||||||
*/
|
*/
|
||||||
get user(): User {
|
get user(): User {
|
||||||
if (!this._user) {
|
if (!this._user) {
|
||||||
this._user = new User(this.client, this._users[this.raw.userId])
|
this._user = new User(
|
||||||
|
this.client,
|
||||||
|
this._peers.user(this.raw.userId)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._user
|
return this._user
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { makeInspectable } from '../utils'
|
import { makeInspectable } from '../utils'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { PeerType, User, UsersIndex } from '../peers'
|
import { PeersIndex, PeerType, User } from '../peers'
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { Location } from '../media'
|
import { Location } from '../media'
|
||||||
import { InputInlineResult } from './input'
|
import { InputInlineResult } from './input'
|
||||||
|
@ -14,20 +14,11 @@ const PEER_TYPE_MAP: Record<tl.TypeInlineQueryPeerType['_'], PeerType> = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InlineQuery {
|
export class InlineQuery {
|
||||||
readonly client: TelegramClient
|
|
||||||
readonly raw: tl.RawUpdateBotInlineQuery
|
|
||||||
|
|
||||||
/** Map of users in this message. Mainly for internal use */
|
|
||||||
readonly _users: UsersIndex
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
readonly client: TelegramClient,
|
||||||
raw: tl.RawUpdateBotInlineQuery,
|
readonly raw: tl.RawUpdateBotInlineQuery,
|
||||||
users: UsersIndex
|
readonly _peers: PeersIndex
|
||||||
) {
|
) {
|
||||||
this.client = client
|
|
||||||
this.raw = raw
|
|
||||||
this._users = users
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,7 +34,7 @@ export class InlineQuery {
|
||||||
*/
|
*/
|
||||||
get user(): User {
|
get user(): User {
|
||||||
if (!this._user) {
|
if (!this._user) {
|
||||||
this._user = new User(this.client, this._users[this.raw.userId])
|
this._user = new User(this.client, this._peers.user(this.raw.userId))
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._user
|
return this._user
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { AsyncLock, getMarkedPeerId, MaybeAsync } from '@mtcute/core'
|
import { AsyncLock, Deque, getMarkedPeerId, MaybeAsync } from '@mtcute/core'
|
||||||
import {
|
import {
|
||||||
ControllablePromise,
|
ControllablePromise,
|
||||||
createControllablePromise,
|
createControllablePromise,
|
||||||
|
@ -12,7 +12,6 @@ import { FormattedString } from './parser'
|
||||||
import { Message } from './messages'
|
import { Message } from './messages'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { TimeoutError } from '@mtcute/tl/errors'
|
import { TimeoutError } from '@mtcute/tl/errors'
|
||||||
import { Queue } from '../utils/queue'
|
|
||||||
|
|
||||||
interface QueuedHandler<T> {
|
interface QueuedHandler<T> {
|
||||||
promise: ControllablePromise<T>
|
promise: ControllablePromise<T>
|
||||||
|
@ -39,12 +38,12 @@ export class Conversation {
|
||||||
private _lastMessage!: number
|
private _lastMessage!: number
|
||||||
private _lastReceivedMessage!: number
|
private _lastReceivedMessage!: number
|
||||||
|
|
||||||
private _queuedNewMessage = new Queue<QueuedHandler<Message>>()
|
private _queuedNewMessage = new Deque<QueuedHandler<Message>>()
|
||||||
private _pendingNewMessages = new Queue<Message>()
|
private _pendingNewMessages = new Deque<Message>()
|
||||||
private _lock = new AsyncLock()
|
private _lock = new AsyncLock()
|
||||||
|
|
||||||
private _pendingEditMessage: Record<number, QueuedHandler<Message>> = {}
|
private _pendingEditMessage: Record<number, QueuedHandler<Message>> = {}
|
||||||
private _recentEdits = new Queue<Message>(10)
|
private _recentEdits = new Deque<Message>(10)
|
||||||
|
|
||||||
private _pendingRead: Record<number, QueuedHandler<void>> = {}
|
private _pendingRead: Record<number, QueuedHandler<void>> = {}
|
||||||
|
|
||||||
|
@ -276,7 +275,7 @@ export class Conversation {
|
||||||
}, timeout)
|
}, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
this._queuedNewMessage.push({
|
this._queuedNewMessage.pushBack({
|
||||||
promise,
|
promise,
|
||||||
check: filter,
|
check: filter,
|
||||||
timeout: timer,
|
timeout: timer,
|
||||||
|
@ -476,12 +475,12 @@ export class Conversation {
|
||||||
private _onNewMessage(msg: Message) {
|
private _onNewMessage(msg: Message) {
|
||||||
if (msg.chat.id !== this._chatId) return
|
if (msg.chat.id !== this._chatId) return
|
||||||
|
|
||||||
if (this._queuedNewMessage.empty()) {
|
if (!this._queuedNewMessage.length) {
|
||||||
this._pendingNewMessages.push(msg)
|
this._pendingNewMessages.pushBack(msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const it = this._queuedNewMessage.peek()!
|
const it = this._queuedNewMessage.peekFront()!
|
||||||
|
|
||||||
// order does matter for new messages
|
// order does matter for new messages
|
||||||
this._lock.acquire().then(async () => {
|
this._lock.acquire().then(async () => {
|
||||||
|
@ -489,7 +488,7 @@ export class Conversation {
|
||||||
if (!it.check || (await it.check(msg))) {
|
if (!it.check || (await it.check(msg))) {
|
||||||
if (it.timeout) clearTimeout(it.timeout)
|
if (it.timeout) clearTimeout(it.timeout)
|
||||||
it.promise.resolve(msg)
|
it.promise.resolve(msg)
|
||||||
this._queuedNewMessage.pop()
|
this._queuedNewMessage.popFront()
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.client['_emitError'](e)
|
this.client['_emitError'](e)
|
||||||
|
@ -507,7 +506,7 @@ export class Conversation {
|
||||||
|
|
||||||
const it = this._pendingEditMessage[msg.id]
|
const it = this._pendingEditMessage[msg.id]
|
||||||
if (!it && !fromRecent) {
|
if (!it && !fromRecent) {
|
||||||
this._recentEdits.push(msg)
|
this._recentEdits.pushBack(msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,21 +535,21 @@ export class Conversation {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _processPendingNewMessages() {
|
private _processPendingNewMessages() {
|
||||||
if (this._pendingNewMessages.empty()) return
|
if (!this._pendingNewMessages.length) return
|
||||||
|
|
||||||
let it
|
let it
|
||||||
while ((it = this._pendingNewMessages.pop())) {
|
while ((it = this._pendingNewMessages.popFront())) {
|
||||||
this._onNewMessage(it)
|
this._onNewMessage(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _processRecentEdits() {
|
private _processRecentEdits() {
|
||||||
if (this._recentEdits.empty()) return
|
if (!this._recentEdits.length) return
|
||||||
|
|
||||||
let it = this._recentEdits.first
|
const iter = this._recentEdits.iter()
|
||||||
do {
|
let it
|
||||||
if (!it) break
|
while (!(it = iter.next()).done) {
|
||||||
this._onEditMessage(it.v, true)
|
this._onEditMessage(it.value, true)
|
||||||
} while ((it = it.n))
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,43 +10,22 @@ import { makeInspectable } from '../utils'
|
||||||
* including ones that are embedded directly into the entity.
|
* including ones that are embedded directly into the entity.
|
||||||
*/
|
*/
|
||||||
export class FileLocation {
|
export class FileLocation {
|
||||||
/**
|
|
||||||
* Client that was used to create this object
|
|
||||||
*/
|
|
||||||
readonly client: TelegramClient
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Location of the file.
|
|
||||||
*
|
|
||||||
* Either a TL object declaring remote file location,
|
|
||||||
* a Buffer containing actual file content (for stripped thumbnails and vector previews),
|
|
||||||
* or a function that will return either of those.
|
|
||||||
*
|
|
||||||
* When a function is passed, it will be lazily resolved the
|
|
||||||
* first time downloading the file.
|
|
||||||
*/
|
|
||||||
readonly location:
|
|
||||||
| tl.TypeInputFileLocation
|
|
||||||
| tl.TypeInputWebFileLocation
|
|
||||||
| Buffer
|
|
||||||
| (() =>
|
|
||||||
| tl.TypeInputFileLocation
|
|
||||||
| tl.TypeInputWebFileLocation
|
|
||||||
| Buffer)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* File size in bytes, when available
|
|
||||||
*/
|
|
||||||
readonly fileSize?: number
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DC ID of the file, when available
|
|
||||||
*/
|
|
||||||
readonly dcId?: number
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
/**
|
||||||
location:
|
* Client that was used to create this object
|
||||||
|
*/
|
||||||
|
readonly client: TelegramClient,
|
||||||
|
/**
|
||||||
|
* Location of the file.
|
||||||
|
*
|
||||||
|
* Either a TL object declaring remote file location,
|
||||||
|
* a Buffer containing actual file content (for stripped thumbnails and vector previews),
|
||||||
|
* or a function that will return either of those.
|
||||||
|
*
|
||||||
|
* When a function is passed, it will be lazily resolved the
|
||||||
|
* first time downloading the file.
|
||||||
|
*/
|
||||||
|
readonly location:
|
||||||
| tl.TypeInputFileLocation
|
| tl.TypeInputFileLocation
|
||||||
| tl.TypeInputWebFileLocation
|
| tl.TypeInputWebFileLocation
|
||||||
| Buffer
|
| Buffer
|
||||||
|
@ -54,13 +33,15 @@ export class FileLocation {
|
||||||
| tl.TypeInputFileLocation
|
| tl.TypeInputFileLocation
|
||||||
| tl.TypeInputWebFileLocation
|
| tl.TypeInputWebFileLocation
|
||||||
| Buffer),
|
| Buffer),
|
||||||
fileSize?: number,
|
/**
|
||||||
dcId?: number
|
* File size in bytes, when available
|
||||||
|
*/
|
||||||
|
readonly fileSize?: number,
|
||||||
|
/**
|
||||||
|
* DC ID of the file, when available
|
||||||
|
*/
|
||||||
|
readonly dcId?: number
|
||||||
) {
|
) {
|
||||||
this.client = client
|
|
||||||
this.location = location
|
|
||||||
this.fileSize = fileSize
|
|
||||||
this.dcId = dcId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,9 +21,7 @@ const STUB_LOCATION = () => {
|
||||||
* > To be sure, check `isDownloadable` property.
|
* > To be sure, check `isDownloadable` property.
|
||||||
*/
|
*/
|
||||||
export class WebDocument extends FileLocation {
|
export class WebDocument extends FileLocation {
|
||||||
readonly raw: tl.TypeWebDocument
|
constructor(client: TelegramClient, readonly raw: tl.TypeWebDocument) {
|
||||||
|
|
||||||
constructor(client: TelegramClient, raw: tl.TypeWebDocument) {
|
|
||||||
super(
|
super(
|
||||||
client,
|
client,
|
||||||
raw._ === 'webDocument'
|
raw._ === 'webDocument'
|
||||||
|
|
|
@ -10,8 +10,6 @@ import { tdFileId } from '@mtcute/file-id'
|
||||||
export class Audio extends RawDocument {
|
export class Audio extends RawDocument {
|
||||||
readonly type = 'audio' as const
|
readonly type = 'audio' as const
|
||||||
|
|
||||||
readonly attr: tl.RawDocumentAttributeAudio
|
|
||||||
|
|
||||||
protected _fileIdType(): tdFileId.FileType {
|
protected _fileIdType(): tdFileId.FileType {
|
||||||
return tdFileId.FileType.Audio
|
return tdFileId.FileType.Audio
|
||||||
}
|
}
|
||||||
|
@ -19,10 +17,9 @@ export class Audio extends RawDocument {
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
client: TelegramClient,
|
||||||
doc: tl.RawDocument,
|
doc: tl.RawDocument,
|
||||||
attr: tl.RawDocumentAttributeAudio
|
readonly attr: tl.RawDocumentAttributeAudio
|
||||||
) {
|
) {
|
||||||
super(client, doc)
|
super(client, doc)
|
||||||
this.attr = attr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,11 +7,7 @@ import { makeInspectable } from '../utils'
|
||||||
export class Contact {
|
export class Contact {
|
||||||
readonly type = 'contact' as const
|
readonly type = 'contact' as const
|
||||||
|
|
||||||
readonly obj: tl.RawMessageMediaContact
|
constructor(readonly obj: tl.RawMessageMediaContact) {}
|
||||||
|
|
||||||
constructor(obj: tl.RawMessageMediaContact) {
|
|
||||||
this.obj = obj
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contact's phone number
|
* Contact's phone number
|
||||||
|
|
|
@ -7,8 +7,6 @@ import { makeInspectable } from '../utils'
|
||||||
export class Dice {
|
export class Dice {
|
||||||
readonly type = 'dice' as const
|
readonly type = 'dice' as const
|
||||||
|
|
||||||
readonly obj: tl.RawMessageMediaDice
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple 6-sided dice.
|
* A simple 6-sided dice.
|
||||||
*
|
*
|
||||||
|
@ -138,9 +136,7 @@ export class Dice {
|
||||||
*/
|
*/
|
||||||
static readonly TYPE_SLOTS = '🎰'
|
static readonly TYPE_SLOTS = '🎰'
|
||||||
|
|
||||||
constructor(obj: tl.RawMessageMediaDice) {
|
constructor(readonly obj: tl.RawMessageMediaDice) {}
|
||||||
this.obj = obj
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An emoji which was originally sent.
|
* An emoji which was originally sent.
|
||||||
|
|
|
@ -11,25 +11,20 @@ import { tdFileId as td, toFileId, toUniqueFileId } from '@mtcute/file-id'
|
||||||
* This also includes audios, videos, voices etc.
|
* This also includes audios, videos, voices etc.
|
||||||
*/
|
*/
|
||||||
export class RawDocument extends FileLocation {
|
export class RawDocument extends FileLocation {
|
||||||
/**
|
constructor(client: TelegramClient, readonly raw: tl.RawDocument) {
|
||||||
* Raw TL object with the document itself
|
|
||||||
*/
|
|
||||||
readonly doc: tl.RawDocument
|
|
||||||
|
|
||||||
constructor(client: TelegramClient, doc: tl.RawDocument) {
|
|
||||||
super(
|
super(
|
||||||
client,
|
client,
|
||||||
{
|
{
|
||||||
_: 'inputDocumentFileLocation',
|
_: 'inputDocumentFileLocation',
|
||||||
id: doc.id,
|
id: raw.id,
|
||||||
fileReference: doc.fileReference,
|
fileReference: raw.fileReference,
|
||||||
accessHash: doc.accessHash,
|
accessHash: raw.accessHash,
|
||||||
thumbSize: '',
|
thumbSize: '',
|
||||||
},
|
},
|
||||||
doc.size,
|
raw.size,
|
||||||
doc.dcId
|
raw.dcId
|
||||||
)
|
)
|
||||||
this.doc = doc
|
this.raw = raw
|
||||||
}
|
}
|
||||||
|
|
||||||
private _fileName?: string | null
|
private _fileName?: string | null
|
||||||
|
@ -39,7 +34,7 @@ export class RawDocument extends FileLocation {
|
||||||
*/
|
*/
|
||||||
get fileName(): string | null {
|
get fileName(): string | null {
|
||||||
if (this._fileName === undefined) {
|
if (this._fileName === undefined) {
|
||||||
const attr = this.doc.attributes.find(
|
const attr = this.raw.attributes.find(
|
||||||
(it) => it._ === 'documentAttributeFilename'
|
(it) => it._ === 'documentAttributeFilename'
|
||||||
)
|
)
|
||||||
this._fileName = attr
|
this._fileName = attr
|
||||||
|
@ -54,14 +49,14 @@ export class RawDocument extends FileLocation {
|
||||||
* File MIME type, as defined by the sender.
|
* File MIME type, as defined by the sender.
|
||||||
*/
|
*/
|
||||||
get mimeType(): string {
|
get mimeType(): string {
|
||||||
return this.doc.mimeType
|
return this.raw.mimeType
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Date the document was sent
|
* Date the document was sent
|
||||||
*/
|
*/
|
||||||
get date(): Date {
|
get date(): Date {
|
||||||
return new Date(this.doc.date * 1000)
|
return new Date(this.raw.date * 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
private _thumbnails?: Thumbnail[]
|
private _thumbnails?: Thumbnail[]
|
||||||
|
@ -72,9 +67,9 @@ export class RawDocument extends FileLocation {
|
||||||
*/
|
*/
|
||||||
get thumbnails(): ReadonlyArray<Thumbnail> {
|
get thumbnails(): ReadonlyArray<Thumbnail> {
|
||||||
if (!this._thumbnails) {
|
if (!this._thumbnails) {
|
||||||
this._thumbnails = this.doc.thumbs
|
this._thumbnails = this.raw.thumbs
|
||||||
? this.doc.thumbs.map(
|
? this.raw.thumbs.map(
|
||||||
(sz) => new Thumbnail(this.client, this.doc, sz)
|
(sz) => new Thumbnail(this.client, this.raw, sz)
|
||||||
)
|
)
|
||||||
: []
|
: []
|
||||||
}
|
}
|
||||||
|
@ -102,9 +97,9 @@ export class RawDocument extends FileLocation {
|
||||||
get inputDocument(): tl.TypeInputDocument {
|
get inputDocument(): tl.TypeInputDocument {
|
||||||
return {
|
return {
|
||||||
_: 'inputDocument',
|
_: 'inputDocument',
|
||||||
id: this.doc.id,
|
id: this.raw.id,
|
||||||
accessHash: this.doc.accessHash,
|
accessHash: this.raw.accessHash,
|
||||||
fileReference: this.doc.fileReference,
|
fileReference: this.raw.fileReference,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,12 +128,12 @@ export class RawDocument extends FileLocation {
|
||||||
if (!this._fileId) {
|
if (!this._fileId) {
|
||||||
this._fileId = toFileId({
|
this._fileId = toFileId({
|
||||||
type: this._fileIdType(),
|
type: this._fileIdType(),
|
||||||
dcId: this.doc.dcId,
|
dcId: this.raw.dcId,
|
||||||
fileReference: this.doc.fileReference,
|
fileReference: this.raw.fileReference,
|
||||||
location: {
|
location: {
|
||||||
_: 'common',
|
_: 'common',
|
||||||
id: this.doc.id,
|
id: this.raw.id,
|
||||||
accessHash: this.doc.accessHash,
|
accessHash: this.raw.accessHash,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -154,7 +149,7 @@ export class RawDocument extends FileLocation {
|
||||||
if (!this._uniqueFileId) {
|
if (!this._uniqueFileId) {
|
||||||
this._uniqueFileId = toUniqueFileId(td.FileType.Document, {
|
this._uniqueFileId = toUniqueFileId(td.FileType.Document, {
|
||||||
_: 'common',
|
_: 'common',
|
||||||
id: this.doc.id,
|
id: this.raw.id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,7 @@ import { makeInspectable } from '../utils'
|
||||||
export class Game {
|
export class Game {
|
||||||
readonly type = 'game' as const
|
readonly type = 'game' as const
|
||||||
|
|
||||||
readonly game: tl.RawGame
|
constructor(readonly client: TelegramClient, readonly game: tl.RawGame) {}
|
||||||
readonly client: TelegramClient
|
|
||||||
|
|
||||||
constructor(client: TelegramClient, game: tl.RawGame) {
|
|
||||||
this.client = client
|
|
||||||
this.game = game
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unique identifier of the game.
|
* Unique identifier of the game.
|
||||||
|
|
|
@ -10,13 +10,10 @@ import { MtArgumentError } from '../errors'
|
||||||
export class Invoice {
|
export class Invoice {
|
||||||
readonly type = 'invoice' as const
|
readonly type = 'invoice' as const
|
||||||
|
|
||||||
readonly client: TelegramClient
|
constructor(
|
||||||
readonly raw: tl.RawMessageMediaInvoice
|
readonly client: TelegramClient,
|
||||||
|
readonly raw: tl.RawMessageMediaInvoice
|
||||||
constructor(client: TelegramClient, raw: tl.RawMessageMediaInvoice) {
|
) {}
|
||||||
this.client = client
|
|
||||||
this.raw = raw
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the shipping address was requested
|
* Whether the shipping address was requested
|
||||||
|
|
|
@ -7,13 +7,10 @@ import { TelegramClient } from '../../client'
|
||||||
* A point on the map
|
* A point on the map
|
||||||
*/
|
*/
|
||||||
export class RawLocation {
|
export class RawLocation {
|
||||||
readonly client: TelegramClient
|
constructor(
|
||||||
readonly geo: tl.RawGeoPoint
|
readonly client: TelegramClient,
|
||||||
|
readonly geo: tl.RawGeoPoint
|
||||||
constructor(client: TelegramClient, geo: tl.RawGeoPoint) {
|
) {}
|
||||||
this.client = client
|
|
||||||
this.geo = geo
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Geo point latitude
|
* Geo point latitude
|
||||||
|
@ -112,11 +109,8 @@ export class Location extends RawLocation {
|
||||||
export class LiveLocation extends RawLocation {
|
export class LiveLocation extends RawLocation {
|
||||||
readonly type = 'live_location' as const
|
readonly type = 'live_location' as const
|
||||||
|
|
||||||
readonly live: tl.RawMessageMediaGeoLive
|
constructor(client: TelegramClient, readonly live: tl.RawMessageMediaGeoLive) {
|
||||||
|
|
||||||
constructor(client: TelegramClient, live: tl.RawMessageMediaGeoLive) {
|
|
||||||
super(client, live.geo as tl.RawGeoPoint)
|
super(client, live.geo as tl.RawGeoPoint)
|
||||||
this.live = live
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,8 +2,8 @@ import { makeInspectable } from '../utils'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { MessageEntity } from '../messages'
|
import { MessageEntity } from '../messages'
|
||||||
import bigInt from 'big-integer'
|
import { PeersIndex } from '../peers'
|
||||||
import { UsersIndex } from '../peers'
|
import Long from 'long'
|
||||||
|
|
||||||
export namespace Poll {
|
export namespace Poll {
|
||||||
export interface PollAnswer {
|
export interface PollAnswer {
|
||||||
|
@ -40,23 +40,12 @@ export namespace Poll {
|
||||||
export class Poll {
|
export class Poll {
|
||||||
readonly type = 'poll' as const
|
readonly type = 'poll' as const
|
||||||
|
|
||||||
readonly client: TelegramClient
|
|
||||||
readonly raw: tl.TypePoll
|
|
||||||
readonly results?: tl.TypePollResults
|
|
||||||
|
|
||||||
readonly _users: UsersIndex
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
readonly client: TelegramClient,
|
||||||
raw: tl.TypePoll,
|
readonly raw: tl.TypePoll,
|
||||||
users: UsersIndex,
|
readonly _peers: PeersIndex,
|
||||||
results?: tl.TypePollResults
|
readonly results?: tl.TypePollResults
|
||||||
) {
|
) {}
|
||||||
this.client = client
|
|
||||||
this.raw = raw
|
|
||||||
this._users = users
|
|
||||||
this.results = results
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unique identifier of the poll
|
* Unique identifier of the poll
|
||||||
|
@ -151,6 +140,7 @@ export class Poll {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _entities?: MessageEntity[]
|
private _entities?: MessageEntity[]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format entities for {@link solution}, only available
|
* Format entities for {@link solution}, only available
|
||||||
* in case you have already answered
|
* in case you have already answered
|
||||||
|
@ -206,7 +196,7 @@ export class Poll {
|
||||||
poll: {
|
poll: {
|
||||||
_: 'poll',
|
_: 'poll',
|
||||||
closed: false,
|
closed: false,
|
||||||
id: bigInt.zero,
|
id: Long.ZERO,
|
||||||
publicVoters: this.raw.publicVoters,
|
publicVoters: this.raw.publicVoters,
|
||||||
multipleChoice: this.raw.multipleChoice,
|
multipleChoice: this.raw.multipleChoice,
|
||||||
question: this.raw.question,
|
question: this.raw.question,
|
||||||
|
|
|
@ -42,9 +42,6 @@ const MASK_POS = ['forehead', 'eyes', 'mouth', 'chin'] as const
|
||||||
export class Sticker extends RawDocument {
|
export class Sticker extends RawDocument {
|
||||||
readonly type = 'sticker' as const
|
readonly type = 'sticker' as const
|
||||||
|
|
||||||
readonly attr: tl.RawDocumentAttributeSticker
|
|
||||||
readonly attrSize?: tl.RawDocumentAttributeImageSize
|
|
||||||
|
|
||||||
protected _fileIdType(): tdFileId.FileType {
|
protected _fileIdType(): tdFileId.FileType {
|
||||||
return tdFileId.FileType.Sticker
|
return tdFileId.FileType.Sticker
|
||||||
}
|
}
|
||||||
|
@ -52,12 +49,10 @@ export class Sticker extends RawDocument {
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
client: TelegramClient,
|
||||||
doc: tl.RawDocument,
|
doc: tl.RawDocument,
|
||||||
attr: tl.RawDocumentAttributeSticker,
|
readonly attr: tl.RawDocumentAttributeSticker,
|
||||||
attrSize?: tl.RawDocumentAttributeImageSize
|
readonly attrSize?: tl.RawDocumentAttributeImageSize
|
||||||
) {
|
) {
|
||||||
super(client, doc)
|
super(client, doc)
|
||||||
this.attr = attr
|
|
||||||
this.attrSize = attrSize
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,7 +172,7 @@ export class Sticker extends RawDocument {
|
||||||
const set = await this.getStickerSet()
|
const set = await this.getStickerSet()
|
||||||
if (!set) return ''
|
if (!set) return ''
|
||||||
|
|
||||||
return set.stickers.find((it) => it.sticker.doc.id.eq(this.doc.id))!
|
return set.stickers.find((it) => it.sticker.raw.id.eq(this.raw.id))!
|
||||||
.emoji
|
.emoji
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { MtArgumentError, MtTypeAssertionError } from '../errors'
|
||||||
import { assertTypeIs } from '../../utils/type-assertion'
|
import { assertTypeIs } from '../../utils/type-assertion'
|
||||||
import { makeInspectable } from '../utils'
|
import { makeInspectable } from '../utils'
|
||||||
import { tdFileId as td, toFileId, toUniqueFileId } from '@mtcute/file-id'
|
import { tdFileId as td, toFileId, toUniqueFileId } from '@mtcute/file-id'
|
||||||
import bigInt from 'big-integer'
|
import Long from 'long'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* One size of some thumbnail
|
* One size of some thumbnail
|
||||||
|
@ -171,8 +171,8 @@ export class Thumbnail extends FileLocation {
|
||||||
fileReference: null,
|
fileReference: null,
|
||||||
location: {
|
location: {
|
||||||
_: 'photo',
|
_: 'photo',
|
||||||
id: bigInt.zero,
|
id: Long.ZERO,
|
||||||
accessHash: bigInt.zero,
|
accessHash: Long.ZERO,
|
||||||
source: {
|
source: {
|
||||||
_: 'stickerSetThumbnailVersion',
|
_: 'stickerSetThumbnailVersion',
|
||||||
id: this._media.id,
|
id: this._media.id,
|
||||||
|
@ -226,7 +226,7 @@ export class Thumbnail extends FileLocation {
|
||||||
if (this._media._ === 'stickerSet') {
|
if (this._media._ === 'stickerSet') {
|
||||||
this._uniqueFileId = toUniqueFileId(td.FileType.Thumbnail, {
|
this._uniqueFileId = toUniqueFileId(td.FileType.Thumbnail, {
|
||||||
_: 'photo',
|
_: 'photo',
|
||||||
id: bigInt.zero,
|
id: Long.ZERO,
|
||||||
source: {
|
source: {
|
||||||
_: 'stickerSetThumbnailVersion',
|
_: 'stickerSetThumbnailVersion',
|
||||||
id: this._media.id,
|
id: this._media.id,
|
||||||
|
|
|
@ -31,13 +31,10 @@ export namespace Venue {
|
||||||
export class Venue {
|
export class Venue {
|
||||||
readonly type = 'venue' as const
|
readonly type = 'venue' as const
|
||||||
|
|
||||||
readonly client: TelegramClient
|
constructor(
|
||||||
readonly raw: tl.RawMessageMediaVenue
|
readonly client: TelegramClient,
|
||||||
|
readonly raw: tl.RawMessageMediaVenue
|
||||||
constructor(client: TelegramClient, raw: tl.RawMessageMediaVenue) {
|
) {}
|
||||||
this.client = client
|
|
||||||
this.raw = raw
|
|
||||||
}
|
|
||||||
|
|
||||||
private _location?: Location
|
private _location?: Location
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,10 +12,6 @@ import { tdFileId } from '@mtcute/file-id'
|
||||||
export class Video extends RawDocument {
|
export class Video extends RawDocument {
|
||||||
readonly type = 'video' as const
|
readonly type = 'video' as const
|
||||||
|
|
||||||
readonly attr:
|
|
||||||
| tl.RawDocumentAttributeVideo
|
|
||||||
| tl.RawDocumentAttributeImageSize
|
|
||||||
|
|
||||||
protected _fileIdType(): tdFileId.FileType {
|
protected _fileIdType(): tdFileId.FileType {
|
||||||
return this.isRound
|
return this.isRound
|
||||||
? tdFileId.FileType.VideoNote
|
? tdFileId.FileType.VideoNote
|
||||||
|
@ -27,10 +23,11 @@ export class Video extends RawDocument {
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
client: TelegramClient,
|
||||||
doc: tl.RawDocument,
|
doc: tl.RawDocument,
|
||||||
attr: tl.RawDocumentAttributeVideo | tl.RawDocumentAttributeImageSize
|
readonly attr:
|
||||||
|
| tl.RawDocumentAttributeVideo
|
||||||
|
| tl.RawDocumentAttributeImageSize
|
||||||
) {
|
) {
|
||||||
super(client, doc)
|
super(client, doc)
|
||||||
this.attr = attr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -65,7 +62,7 @@ export class Video extends RawDocument {
|
||||||
if (!this._isAnimation) {
|
if (!this._isAnimation) {
|
||||||
this._isAnimation =
|
this._isAnimation =
|
||||||
this.attr._ === 'documentAttributeImageSize' ||
|
this.attr._ === 'documentAttributeImageSize' ||
|
||||||
this.doc.attributes.some(
|
this.raw.attributes.some(
|
||||||
(it) => it._ === 'documentAttributeAnimated'
|
(it) => it._ === 'documentAttributeAnimated'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,6 @@ import { decodeWaveform } from '../../utils/voice-utils'
|
||||||
export class Voice extends RawDocument {
|
export class Voice extends RawDocument {
|
||||||
readonly type = 'voice' as const
|
readonly type = 'voice' as const
|
||||||
|
|
||||||
readonly attr: tl.RawDocumentAttributeAudio
|
|
||||||
|
|
||||||
protected _fileIdType(): tdFileId.FileType {
|
protected _fileIdType(): tdFileId.FileType {
|
||||||
return tdFileId.FileType.VoiceNote
|
return tdFileId.FileType.VoiceNote
|
||||||
}
|
}
|
||||||
|
@ -20,10 +18,9 @@ export class Voice extends RawDocument {
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
client: TelegramClient,
|
||||||
doc: tl.RawDocument,
|
doc: tl.RawDocument,
|
||||||
attr: tl.RawDocumentAttributeAudio
|
readonly attr: tl.RawDocumentAttributeAudio
|
||||||
) {
|
) {
|
||||||
super(client, doc)
|
super(client, doc)
|
||||||
this.attr = attr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -19,13 +19,7 @@ import { MtArgumentError } from '../errors'
|
||||||
export class WebPage {
|
export class WebPage {
|
||||||
readonly type = 'web_page' as const
|
readonly type = 'web_page' as const
|
||||||
|
|
||||||
readonly client: TelegramClient
|
constructor(readonly client: TelegramClient, readonly raw: tl.RawWebPage) {}
|
||||||
readonly raw: tl.RawWebPage
|
|
||||||
|
|
||||||
constructor(client: TelegramClient, raw: tl.RawWebPage) {
|
|
||||||
this.client = client
|
|
||||||
this.raw = raw
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unique ID of the preview
|
* Unique ID of the preview
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { Chat, ChatsIndex, UsersIndex } from '../peers'
|
import { Chat, PeersIndex } from '../peers'
|
||||||
import { Message } from './message'
|
import { Message } from './message'
|
||||||
import { DraftMessage } from './draft-message'
|
import { DraftMessage } from './draft-message'
|
||||||
import { makeInspectable } from '../utils'
|
import { makeInspectable } from '../utils'
|
||||||
|
@ -13,31 +13,12 @@ import { getMarkedPeerId, MessageNotFoundError } from '@mtcute/core'
|
||||||
* in Telegram's main window.
|
* in Telegram's main window.
|
||||||
*/
|
*/
|
||||||
export class Dialog {
|
export class Dialog {
|
||||||
readonly client: TelegramClient
|
|
||||||
readonly raw: tl.RawDialog
|
|
||||||
|
|
||||||
/** Map of users in this object. Mainly for internal use */
|
|
||||||
readonly _users: UsersIndex
|
|
||||||
|
|
||||||
/** Map of chats in this object. Mainly for internal use */
|
|
||||||
readonly _chats: ChatsIndex
|
|
||||||
|
|
||||||
/** Map of messages in this object. Mainly for internal use */
|
|
||||||
readonly _messages: Record<number, tl.TypeMessage>
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
readonly client: TelegramClient,
|
||||||
raw: tl.RawDialog,
|
readonly raw: tl.RawDialog,
|
||||||
users: UsersIndex,
|
readonly _peers: PeersIndex,
|
||||||
chats: ChatsIndex,
|
readonly _messages: Record<number, tl.TypeMessage>
|
||||||
messages: Record<number, tl.TypeMessage>
|
) {}
|
||||||
) {
|
|
||||||
this.client = client
|
|
||||||
this.raw = raw
|
|
||||||
this._users = users
|
|
||||||
this._chats = chats
|
|
||||||
this._messages = messages
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find pinned dialogs from a list of dialogs
|
* Find pinned dialogs from a list of dialogs
|
||||||
|
@ -172,12 +153,12 @@ export class Dialog {
|
||||||
switch (peer._) {
|
switch (peer._) {
|
||||||
case 'peerChannel':
|
case 'peerChannel':
|
||||||
case 'peerChat':
|
case 'peerChat':
|
||||||
chat = this._chats[
|
chat = this._peers.chat(
|
||||||
peer._ === 'peerChannel' ? peer.channelId : peer.chatId
|
peer._ === 'peerChannel' ? peer.channelId : peer.chatId
|
||||||
]
|
)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
chat = this._users[peer.userId]
|
chat = this._peers.user(peer.userId)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,8 +181,7 @@ export class Dialog {
|
||||||
this._lastMessage = new Message(
|
this._lastMessage = new Message(
|
||||||
this.client,
|
this.client,
|
||||||
this._messages[cid],
|
this._messages[cid],
|
||||||
this._users,
|
this._peers
|
||||||
this._chats
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
throw new MessageNotFoundError()
|
throw new MessageNotFoundError()
|
||||||
|
|
|
@ -10,19 +10,11 @@ import { makeInspectable } from '../utils'
|
||||||
import { InputMediaWithCaption } from '../media'
|
import { InputMediaWithCaption } from '../media'
|
||||||
|
|
||||||
export class DraftMessage {
|
export class DraftMessage {
|
||||||
readonly client: TelegramClient
|
|
||||||
readonly raw: tl.RawDraftMessage
|
|
||||||
|
|
||||||
private _chatId: InputPeerLike
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
readonly client: TelegramClient,
|
||||||
raw: tl.RawDraftMessage,
|
readonly raw: tl.RawDraftMessage,
|
||||||
chatId: InputPeerLike
|
readonly _chatId: InputPeerLike
|
||||||
) {
|
) {
|
||||||
this.client = client
|
|
||||||
this.raw = raw
|
|
||||||
this._chatId = chatId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -69,7 +69,7 @@ export function _messageMediaFromTl(
|
||||||
case 'messageMediaVenue':
|
case 'messageMediaVenue':
|
||||||
return new Venue(this.client, m)
|
return new Venue(this.client, m)
|
||||||
case 'messageMediaPoll':
|
case 'messageMediaPoll':
|
||||||
return new Poll(this.client, m.poll, this._users, m.results)
|
return new Poll(this.client, m.poll, this._peers, m.results)
|
||||||
case 'messageMediaInvoice':
|
case 'messageMediaInvoice':
|
||||||
return new Invoice(this.client, m)
|
return new Invoice(this.client, m)
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { User, Chat, InputPeerLike, UsersIndex, ChatsIndex } from '../peers'
|
import { User, Chat, InputPeerLike, PeersIndex } from '../peers'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { BotKeyboard, ReplyMarkup } from '../bots'
|
import { BotKeyboard, ReplyMarkup } from '../bots'
|
||||||
import { getMarkedPeerId, MAX_CHANNEL_ID } from '@mtcute/core'
|
import { getMarkedPeerId, toggleChannelIdMark } from '@mtcute/core'
|
||||||
import {
|
import {
|
||||||
MtArgumentError,
|
MtArgumentError,
|
||||||
MtTypeAssertionError,
|
MtTypeAssertionError,
|
||||||
|
@ -96,44 +96,31 @@ export namespace Message {
|
||||||
* A Telegram message.
|
* A Telegram message.
|
||||||
*/
|
*/
|
||||||
export class Message {
|
export class Message {
|
||||||
/** Telegram client that received this message */
|
|
||||||
readonly client: TelegramClient
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Raw TL object.
|
* Raw TL object.
|
||||||
*/
|
*/
|
||||||
readonly raw: tl.RawMessage | tl.RawMessageService
|
readonly raw: tl.RawMessage | tl.RawMessageService
|
||||||
|
|
||||||
/** Map of users in this message. Mainly for internal use */
|
|
||||||
readonly _users: UsersIndex
|
|
||||||
/** Map of chats in this message. Mainly for internal use */
|
|
||||||
readonly _chats: ChatsIndex
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
readonly client: TelegramClient,
|
||||||
raw: tl.TypeMessage,
|
raw: tl.TypeMessage,
|
||||||
users: UsersIndex,
|
readonly _peers: PeersIndex,
|
||||||
chats: ChatsIndex,
|
/**
|
||||||
isScheduled = false
|
* Whether the message is scheduled.
|
||||||
|
* If it is, then its {@link date} is set to future.
|
||||||
|
*/
|
||||||
|
readonly isScheduled = false
|
||||||
) {
|
) {
|
||||||
if (raw._ === 'messageEmpty')
|
if (raw._ === 'messageEmpty')
|
||||||
throw new MtTypeAssertionError('Message#ctor', 'not messageEmpty', 'messageEmpty')
|
throw new MtTypeAssertionError(
|
||||||
|
'Message#ctor',
|
||||||
this.client = client
|
'not messageEmpty',
|
||||||
this._users = users
|
'messageEmpty'
|
||||||
this._chats = chats
|
)
|
||||||
|
|
||||||
this.raw = raw
|
this.raw = raw
|
||||||
|
|
||||||
this.isScheduled = isScheduled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the message is scheduled.
|
|
||||||
* If it is, then its {@link date} is set to future.
|
|
||||||
*/
|
|
||||||
readonly isScheduled: boolean
|
|
||||||
|
|
||||||
/** Unique message identifier inside this chat */
|
/** Unique message identifier inside this chat */
|
||||||
get id(): number {
|
get id(): number {
|
||||||
return this.raw.id
|
return this.raw.id
|
||||||
|
@ -197,7 +184,7 @@ export class Message {
|
||||||
if (this.raw.peerId._ === 'peerUser') {
|
if (this.raw.peerId._ === 'peerUser') {
|
||||||
this._sender = new User(
|
this._sender = new User(
|
||||||
this.client,
|
this.client,
|
||||||
this._users[this.raw.peerId.userId]
|
this._peers.user(this.raw.peerId.userId)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// anon admin, return the chat
|
// anon admin, return the chat
|
||||||
|
@ -208,13 +195,13 @@ export class Message {
|
||||||
case 'peerChannel': // forwarded channel post
|
case 'peerChannel': // forwarded channel post
|
||||||
this._sender = new Chat(
|
this._sender = new Chat(
|
||||||
this.client,
|
this.client,
|
||||||
this._chats[from.channelId]
|
this._peers.chat(from.channelId)
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
case 'peerUser':
|
case 'peerUser':
|
||||||
this._sender = new User(
|
this._sender = new User(
|
||||||
this.client,
|
this.client,
|
||||||
this._users[from.userId]
|
this._peers.user(from.userId)
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
@ -239,8 +226,7 @@ export class Message {
|
||||||
this._chat = Chat._parseFromMessage(
|
this._chat = Chat._parseFromMessage(
|
||||||
this.client,
|
this.client,
|
||||||
this.raw,
|
this.raw,
|
||||||
this._users,
|
this._peers
|
||||||
this._chats
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,13 +260,13 @@ export class Message {
|
||||||
case 'peerChannel':
|
case 'peerChannel':
|
||||||
sender = new Chat(
|
sender = new Chat(
|
||||||
this.client,
|
this.client,
|
||||||
this._chats[fwd.fromId.channelId]
|
this._peers.chat(fwd.fromId.channelId)
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
case 'peerUser':
|
case 'peerUser':
|
||||||
sender = new User(
|
sender = new User(
|
||||||
this.client,
|
this.client,
|
||||||
this._users[fwd.fromId.userId]
|
this._peers.user(fwd.fromId.userId)
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
@ -329,7 +315,7 @@ export class Message {
|
||||||
|
|
||||||
if (r.comments) {
|
if (r.comments) {
|
||||||
const o = (obj as unknown) as Message.MessageCommentsInfo
|
const o = (obj as unknown) as Message.MessageCommentsInfo
|
||||||
o.discussion = r.channelId!
|
o.discussion = getMarkedPeerId(r.channelId!, 'channel')
|
||||||
o.repliers =
|
o.repliers =
|
||||||
r.recentRepliers?.map((it) => getMarkedPeerId(it)) ?? []
|
r.recentRepliers?.map((it) => getMarkedPeerId(it)) ?? []
|
||||||
}
|
}
|
||||||
|
@ -375,7 +361,7 @@ export class Message {
|
||||||
} else {
|
} else {
|
||||||
this._viaBot = new User(
|
this._viaBot = new User(
|
||||||
this.client,
|
this.client,
|
||||||
this._users[this.raw.viaBotId]
|
this._peers.user(this.raw.viaBotId)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -515,7 +501,7 @@ export class Message {
|
||||||
if (this.chat.username) {
|
if (this.chat.username) {
|
||||||
return `https://t.me/${this.chat.username}/${this.id}`
|
return `https://t.me/${this.chat.username}/${this.id}`
|
||||||
} else {
|
} else {
|
||||||
return `https://t.me/c/${MAX_CHANNEL_ID - this.chat.id}/${
|
return `https://t.me/c/${toggleChannelIdMark(this.chat.id)}/${
|
||||||
this.id
|
this.id
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
|
@ -547,8 +533,7 @@ export class Message {
|
||||||
* this method will also return `null`.
|
* this method will also return `null`.
|
||||||
*/
|
*/
|
||||||
getReplyTo(): Promise<Message | null> {
|
getReplyTo(): Promise<Message | null> {
|
||||||
if (!this.replyToMessageId)
|
if (!this.replyToMessageId) return Promise.resolve(null)
|
||||||
return Promise.resolve(null)
|
|
||||||
|
|
||||||
if (this.raw.peerId._ === 'peerChannel')
|
if (this.raw.peerId._ === 'peerChannel')
|
||||||
return this.client.getMessages(this.chat.inputPeer, this.id, true)
|
return this.client.getMessages(this.chat.inputPeer, this.id, true)
|
||||||
|
@ -795,7 +780,7 @@ export class Message {
|
||||||
* passing positional `text` as object field.
|
* passing positional `text` as object field.
|
||||||
*
|
*
|
||||||
* @param text New message text
|
* @param text New message text
|
||||||
* @param params Additional parameters
|
* @param params? Additional parameters
|
||||||
* @link TelegramClient.editMessage
|
* @link TelegramClient.editMessage
|
||||||
*/
|
*/
|
||||||
editText(
|
editText(
|
||||||
|
@ -819,7 +804,12 @@ export class Message {
|
||||||
peer: InputPeerLike,
|
peer: InputPeerLike,
|
||||||
params?: Parameters<TelegramClient['forwardMessages']>[3]
|
params?: Parameters<TelegramClient['forwardMessages']>[3]
|
||||||
): Promise<Message> {
|
): Promise<Message> {
|
||||||
return this.client.forwardMessages(peer, this.chat.inputPeer, this.id, params)
|
return this.client.forwardMessages(
|
||||||
|
peer,
|
||||||
|
this.chat.inputPeer,
|
||||||
|
this.id,
|
||||||
|
params
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -885,7 +875,10 @@ export class Message {
|
||||||
* message.
|
* message.
|
||||||
*/
|
*/
|
||||||
async getDiscussionMessage(): Promise<Message | null> {
|
async getDiscussionMessage(): Promise<Message | null> {
|
||||||
return this.client.getDiscussionMessage(this.chat.inputPeer, this.raw.id)
|
return this.client.getDiscussionMessage(
|
||||||
|
this.chat.inputPeer,
|
||||||
|
this.raw.id
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { tl } from '@mtcute/tl'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search filters to be used in {@link TelegramClient.searchMessages}
|
* Search filters to be used in {@link TelegramClient.searchMessages}
|
||||||
* and {@link TelegramClient.searchGlobal}.
|
* and {@link TelegramClient.searchGlobal}.
|
||||||
|
|
|
@ -32,7 +32,6 @@ export namespace StickerSet {
|
||||||
* A stickerset (aka sticker pack)
|
* A stickerset (aka sticker pack)
|
||||||
*/
|
*/
|
||||||
export class StickerSet {
|
export class StickerSet {
|
||||||
readonly client: TelegramClient
|
|
||||||
readonly brief: tl.RawStickerSet
|
readonly brief: tl.RawStickerSet
|
||||||
readonly full?: tl.messages.RawStickerSet
|
readonly full?: tl.messages.RawStickerSet
|
||||||
|
|
||||||
|
@ -42,10 +41,9 @@ export class StickerSet {
|
||||||
readonly isFull: boolean
|
readonly isFull: boolean
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
readonly client: TelegramClient,
|
||||||
raw: tl.RawStickerSet | tl.messages.RawStickerSet
|
raw: tl.RawStickerSet | tl.messages.RawStickerSet
|
||||||
) {
|
) {
|
||||||
this.client = client
|
|
||||||
if (raw._ === 'messages.stickerSet') {
|
if (raw._ === 'messages.stickerSet') {
|
||||||
this.full = raw
|
this.full = raw
|
||||||
this.brief = raw.set
|
this.brief = raw.set
|
||||||
|
|
|
@ -6,15 +6,15 @@ import { makeInspectable } from '../utils'
|
||||||
* Account takeout session
|
* Account takeout session
|
||||||
*/
|
*/
|
||||||
export class TakeoutSession {
|
export class TakeoutSession {
|
||||||
private client: TelegramClient
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takeout session id
|
* Takeout session id
|
||||||
*/
|
*/
|
||||||
readonly id: tl.Long
|
readonly id: tl.Long
|
||||||
|
|
||||||
constructor(client: TelegramClient, session: tl.account.RawTakeout) {
|
constructor(
|
||||||
this.client = client
|
readonly client: TelegramClient,
|
||||||
|
session: tl.account.RawTakeout
|
||||||
|
) {
|
||||||
this.id = session.id
|
this.id = session.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,9 @@ import { Message } from '../messages'
|
||||||
import { ChatPermissions } from './chat-permissions'
|
import { ChatPermissions } from './chat-permissions'
|
||||||
import { ChatLocation } from './chat-location'
|
import { ChatLocation } from './chat-location'
|
||||||
import { ChatInviteLink } from './chat-invite-link'
|
import { ChatInviteLink } from './chat-invite-link'
|
||||||
import { ChatsIndex, UsersIndex } from './index'
|
import { PeersIndex } from './index'
|
||||||
|
import { toggleChannelIdMark } from '../../../../core'
|
||||||
|
|
||||||
|
|
||||||
export namespace ChatEvent {
|
export namespace ChatEvent {
|
||||||
/** A user has joined the group (in the case of big groups, info of the user that has joined isn't shown) */
|
/** A user has joined the group (in the case of big groups, info of the user that has joined isn't shown) */
|
||||||
|
@ -371,8 +373,7 @@ function _actionFromTl(
|
||||||
message: new Message(
|
message: new Message(
|
||||||
this.client,
|
this.client,
|
||||||
e.message,
|
e.message,
|
||||||
this._users,
|
this._peers
|
||||||
this._chats
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
case 'channelAdminLogEventActionEditMessage':
|
case 'channelAdminLogEventActionEditMessage':
|
||||||
|
@ -381,14 +382,12 @@ function _actionFromTl(
|
||||||
old: new Message(
|
old: new Message(
|
||||||
this.client,
|
this.client,
|
||||||
e.prevMessage,
|
e.prevMessage,
|
||||||
this._users,
|
this._peers
|
||||||
this._chats
|
|
||||||
),
|
),
|
||||||
new: new Message(
|
new: new Message(
|
||||||
this.client,
|
this.client,
|
||||||
e.newMessage,
|
e.newMessage,
|
||||||
this._users,
|
this._peers
|
||||||
this._chats
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
case 'channelAdminLogEventActionDeleteMessage':
|
case 'channelAdminLogEventActionDeleteMessage':
|
||||||
|
@ -397,8 +396,7 @@ function _actionFromTl(
|
||||||
message: new Message(
|
message: new Message(
|
||||||
this.client,
|
this.client,
|
||||||
e.message,
|
e.message,
|
||||||
this._users,
|
this._peers
|
||||||
this._chats
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
case 'channelAdminLogEventActionParticipantLeave':
|
case 'channelAdminLogEventActionParticipantLeave':
|
||||||
|
@ -406,7 +404,7 @@ function _actionFromTl(
|
||||||
case 'channelAdminLogEventActionParticipantInvite':
|
case 'channelAdminLogEventActionParticipantInvite':
|
||||||
return {
|
return {
|
||||||
type: 'user_invited',
|
type: 'user_invited',
|
||||||
member: new ChatMember(this.client, e.participant, this._users),
|
member: new ChatMember(this.client, e.participant, this._peers),
|
||||||
}
|
}
|
||||||
case 'channelAdminLogEventActionParticipantToggleBan':
|
case 'channelAdminLogEventActionParticipantToggleBan':
|
||||||
return {
|
return {
|
||||||
|
@ -414,9 +412,9 @@ function _actionFromTl(
|
||||||
old: new ChatMember(
|
old: new ChatMember(
|
||||||
this.client,
|
this.client,
|
||||||
e.prevParticipant,
|
e.prevParticipant,
|
||||||
this._users
|
this._peers
|
||||||
),
|
),
|
||||||
new: new ChatMember(this.client, e.newParticipant, this._users),
|
new: new ChatMember(this.client, e.newParticipant, this._peers),
|
||||||
}
|
}
|
||||||
case 'channelAdminLogEventActionParticipantToggleAdmin':
|
case 'channelAdminLogEventActionParticipantToggleAdmin':
|
||||||
return {
|
return {
|
||||||
|
@ -424,9 +422,9 @@ function _actionFromTl(
|
||||||
old: new ChatMember(
|
old: new ChatMember(
|
||||||
this.client,
|
this.client,
|
||||||
e.prevParticipant,
|
e.prevParticipant,
|
||||||
this._users
|
this._peers
|
||||||
),
|
),
|
||||||
new: new ChatMember(this.client, e.newParticipant, this._users),
|
new: new ChatMember(this.client, e.newParticipant, this._peers),
|
||||||
}
|
}
|
||||||
case 'channelAdminLogEventActionChangeStickerSet':
|
case 'channelAdminLogEventActionChangeStickerSet':
|
||||||
return {
|
return {
|
||||||
|
@ -452,15 +450,14 @@ function _actionFromTl(
|
||||||
message: new Message(
|
message: new Message(
|
||||||
this.client,
|
this.client,
|
||||||
e.message,
|
e.message,
|
||||||
this._users,
|
this._peers
|
||||||
this._chats
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
case 'channelAdminLogEventActionChangeLinkedChat':
|
case 'channelAdminLogEventActionChangeLinkedChat':
|
||||||
return {
|
return {
|
||||||
type: 'linked_chat_changed',
|
type: 'linked_chat_changed',
|
||||||
old: e.prevValue,
|
old: toggleChannelIdMark(e.prevValue),
|
||||||
new: e.newValue,
|
new: toggleChannelIdMark(e.newValue),
|
||||||
}
|
}
|
||||||
case 'channelAdminLogEventActionChangeLocation':
|
case 'channelAdminLogEventActionChangeLocation':
|
||||||
return {
|
return {
|
||||||
|
@ -503,23 +500,23 @@ function _actionFromTl(
|
||||||
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._peers),
|
||||||
}
|
}
|
||||||
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._peers),
|
||||||
}
|
}
|
||||||
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._peers),
|
||||||
}
|
}
|
||||||
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._peers),
|
||||||
new: new ChatInviteLink(this.client, e.newInvite, this._users),
|
new: new ChatInviteLink(this.client, e.newInvite, this._peers),
|
||||||
}
|
}
|
||||||
case 'channelAdminLogEventActionChangeHistoryTTL':
|
case 'channelAdminLogEventActionChangeHistoryTTL':
|
||||||
return {
|
return {
|
||||||
|
@ -533,22 +530,11 @@ function _actionFromTl(
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ChatEvent {
|
export class ChatEvent {
|
||||||
readonly client: TelegramClient
|
|
||||||
readonly raw: tl.TypeChannelAdminLogEvent
|
|
||||||
|
|
||||||
readonly _users: UsersIndex
|
|
||||||
readonly _chats: ChatsIndex
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
readonly client: TelegramClient,
|
||||||
raw: tl.TypeChannelAdminLogEvent,
|
readonly raw: tl.TypeChannelAdminLogEvent,
|
||||||
users: UsersIndex,
|
readonly _peers: PeersIndex,
|
||||||
chats: ChatsIndex
|
|
||||||
) {
|
) {
|
||||||
this.client = client
|
|
||||||
this.raw = raw
|
|
||||||
this._users = users
|
|
||||||
this._chats = chats
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -574,7 +560,7 @@ export class ChatEvent {
|
||||||
*/
|
*/
|
||||||
get actor(): User {
|
get actor(): User {
|
||||||
if (!this._actor) {
|
if (!this._actor) {
|
||||||
this._actor = new User(this.client, this._users[this.raw.userId])
|
this._actor = new User(this.client, this._peers.user(this.raw.userId))
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._actor
|
return this._actor
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { makeInspectable } from '../utils'
|
||||||
import { TelegramClient } from '../../client'
|
import { TelegramClient } from '../../client'
|
||||||
import { tl } from '@mtcute/tl'
|
import { tl } from '@mtcute/tl'
|
||||||
import { User } from './user'
|
import { User } from './user'
|
||||||
import { UsersIndex } from './index'
|
import { PeersIndex } from './index'
|
||||||
|
|
||||||
export namespace ChatInviteLink {
|
export namespace ChatInviteLink {
|
||||||
export interface JoinedMember {
|
export interface JoinedMember {
|
||||||
|
@ -15,19 +15,11 @@ export namespace ChatInviteLink {
|
||||||
* An invite link
|
* An invite link
|
||||||
*/
|
*/
|
||||||
export class ChatInviteLink {
|
export class ChatInviteLink {
|
||||||
readonly client: TelegramClient
|
|
||||||
readonly raw: tl.RawChatInviteExported
|
|
||||||
|
|
||||||
readonly _users?: UsersIndex
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
readonly client: TelegramClient,
|
||||||
raw: tl.RawChatInviteExported,
|
readonly raw: tl.RawChatInviteExported,
|
||||||
users?: UsersIndex
|
readonly _peers?: PeersIndex
|
||||||
) {
|
) {
|
||||||
this.client = client
|
|
||||||
this.raw = raw
|
|
||||||
this._users = users
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,10 +37,13 @@ export class ChatInviteLink {
|
||||||
* Creator of the invite link, if available
|
* Creator of the invite link, if available
|
||||||
*/
|
*/
|
||||||
get creator(): User | null {
|
get creator(): User | null {
|
||||||
if (!this._users) return null
|
if (!this._peers) return null
|
||||||
|
|
||||||
if (!this._creator) {
|
if (!this._creator) {
|
||||||
this._creator = new User(this.client, this._users[this.raw.adminId])
|
this._creator = new User(
|
||||||
|
this.client,
|
||||||
|
this._peers.user(this.raw.adminId)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._creator
|
return this._creator
|
||||||
|
|
|
@ -7,13 +7,10 @@ import { makeInspectable } from '../utils'
|
||||||
* Geolocation of a supergroup
|
* Geolocation of a supergroup
|
||||||
*/
|
*/
|
||||||
export class ChatLocation {
|
export class ChatLocation {
|
||||||
readonly client: TelegramClient
|
constructor(
|
||||||
readonly raw: tl.RawChannelLocation
|
readonly client: TelegramClient,
|
||||||
|
readonly raw: tl.RawChannelLocation
|
||||||
constructor(client: TelegramClient, raw: tl.RawChannelLocation) {
|
) {}
|
||||||
this.client = client
|
|
||||||
this.raw = raw
|
|
||||||
}
|
|
||||||
|
|
||||||
private _location?: Location
|
private _location?: Location
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { tl } from '@mtcute/tl'
|
||||||
import { User } from './user'
|
import { User } from './user'
|
||||||
import { assertTypeIs } from '../../utils/type-assertion'
|
import { assertTypeIs } from '../../utils/type-assertion'
|
||||||
import { ChatPermissions } from './chat-permissions'
|
import { ChatPermissions } from './chat-permissions'
|
||||||
import { UsersIndex } from './index'
|
import { PeersIndex } from './index'
|
||||||
|
|
||||||
export namespace ChatMember {
|
export namespace ChatMember {
|
||||||
/**
|
/**
|
||||||
|
@ -29,21 +29,11 @@ export namespace ChatMember {
|
||||||
* Information about one chat member
|
* Information about one chat member
|
||||||
*/
|
*/
|
||||||
export class ChatMember {
|
export class ChatMember {
|
||||||
readonly client: TelegramClient
|
|
||||||
readonly raw: tl.TypeChatParticipant | tl.TypeChannelParticipant
|
|
||||||
|
|
||||||
/** Map of users in this object. Mainly for internal use */
|
|
||||||
readonly _users: UsersIndex
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
readonly client: TelegramClient,
|
||||||
raw: tl.TypeChatParticipant | tl.TypeChannelParticipant,
|
readonly raw: tl.TypeChatParticipant | tl.TypeChannelParticipant,
|
||||||
users: UsersIndex
|
readonly _peers: PeersIndex
|
||||||
) {
|
) {}
|
||||||
this.client = client
|
|
||||||
this.raw = raw
|
|
||||||
this._users = users
|
|
||||||
}
|
|
||||||
|
|
||||||
private _user?: User
|
private _user?: User
|
||||||
/**
|
/**
|
||||||
|
@ -59,15 +49,16 @@ export class ChatMember {
|
||||||
this.raw.peer,
|
this.raw.peer,
|
||||||
'peerUser'
|
'peerUser'
|
||||||
)
|
)
|
||||||
|
|
||||||
this._user = new User(
|
this._user = new User(
|
||||||
this.client,
|
this.client,
|
||||||
this._users[this.raw.peer.userId]
|
this._peers.user(this.raw.peer.userId)
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
this._user = new User(
|
this._user = new User(
|
||||||
this.client,
|
this.client,
|
||||||
this._users[this.raw.userId]
|
this._peers.user(this.raw.userId)
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -148,7 +139,7 @@ export class ChatMember {
|
||||||
if ('inviterId' in this.raw && this.raw.inviterId) {
|
if ('inviterId' in this.raw && this.raw.inviterId) {
|
||||||
this._invitedBy = new User(
|
this._invitedBy = new User(
|
||||||
this.client,
|
this.client,
|
||||||
this._users[this.raw.inviterId]
|
this._peers.user(this.raw.inviterId)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
this._invitedBy = null
|
this._invitedBy = null
|
||||||
|
@ -169,7 +160,7 @@ export class ChatMember {
|
||||||
if (this.raw._ === 'channelParticipantAdmin') {
|
if (this.raw._ === 'channelParticipantAdmin') {
|
||||||
this._promotedBy = new User(
|
this._promotedBy = new User(
|
||||||
this.client,
|
this.client,
|
||||||
this._users[this.raw.promotedBy]
|
this._peers.user(this.raw.promotedBy)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
this._promotedBy = null
|
this._promotedBy = null
|
||||||
|
@ -190,7 +181,7 @@ export class ChatMember {
|
||||||
if (this.raw._ === 'channelParticipantBanned') {
|
if (this.raw._ === 'channelParticipantBanned') {
|
||||||
this._restrictedBy = new User(
|
this._restrictedBy = new User(
|
||||||
this.client,
|
this.client,
|
||||||
this._users[this.raw.kickedBy]
|
this._peers.user(this.raw.kickedBy)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
this._restrictedBy = null
|
this._restrictedBy = null
|
||||||
|
|
|
@ -4,23 +4,19 @@ import { TelegramClient } from '../../client'
|
||||||
import { makeInspectable } from '../utils'
|
import { makeInspectable } from '../utils'
|
||||||
import { strippedPhotoToJpg } from '../../utils/file-utils'
|
import { strippedPhotoToJpg } from '../../utils/file-utils'
|
||||||
import { tdFileId, toFileId, toUniqueFileId } from '@mtcute/file-id'
|
import { tdFileId, toFileId, toUniqueFileId } from '@mtcute/file-id'
|
||||||
import bigInt from 'big-integer'
|
|
||||||
import { MAX_CHANNEL_ID } from '@mtcute/core'
|
|
||||||
import { MtArgumentError } from '../errors'
|
import { MtArgumentError } from '../errors'
|
||||||
|
import Long from 'long'
|
||||||
|
import { toggleChannelIdMark } from '../../../../core'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A size of a chat photo
|
* A size of a chat photo
|
||||||
*/
|
*/
|
||||||
export class ChatPhotoSize extends FileLocation {
|
export class ChatPhotoSize extends FileLocation {
|
||||||
readonly obj: tl.RawUserProfilePhoto | tl.RawChatPhoto
|
|
||||||
readonly peer: tl.TypeInputPeer
|
|
||||||
readonly big: boolean
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
readonly client: TelegramClient,
|
||||||
peer: tl.TypeInputPeer,
|
readonly peer: tl.TypeInputPeer,
|
||||||
obj: tl.RawUserProfilePhoto | tl.RawChatPhoto,
|
readonly obj: tl.RawUserProfilePhoto | tl.RawChatPhoto,
|
||||||
big: boolean
|
readonly big: boolean
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
client,
|
client,
|
||||||
|
@ -57,10 +53,10 @@ export class ChatPhotoSize extends FileLocation {
|
||||||
break
|
break
|
||||||
case 'inputPeerChat':
|
case 'inputPeerChat':
|
||||||
id = -peer.chatId
|
id = -peer.chatId
|
||||||
hash = bigInt.zero
|
hash = Long.ZERO
|
||||||
break
|
break
|
||||||
case 'inputPeerChannel':
|
case 'inputPeerChannel':
|
||||||
id = MAX_CHANNEL_ID - peer.channelId
|
id = toggleChannelIdMark(peer.channelId)
|
||||||
hash = peer.accessHash
|
hash = peer.accessHash
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
@ -75,11 +71,11 @@ export class ChatPhotoSize extends FileLocation {
|
||||||
location: {
|
location: {
|
||||||
_: 'photo',
|
_: 'photo',
|
||||||
id: this.obj.photoId,
|
id: this.obj.photoId,
|
||||||
accessHash: bigInt.zero,
|
accessHash: Long.ZERO,
|
||||||
source: {
|
source: {
|
||||||
_: 'dialogPhoto',
|
_: 'dialogPhoto',
|
||||||
big: this.big,
|
big: this.big,
|
||||||
id: bigInt(id),
|
id: id,
|
||||||
accessHash: hash,
|
accessHash: hash,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,19 +16,15 @@ export namespace ChatPreview {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ChatPreview {
|
export class ChatPreview {
|
||||||
readonly client: TelegramClient
|
|
||||||
readonly invite: tl.RawChatInvite
|
|
||||||
|
|
||||||
/**
|
constructor(
|
||||||
* Original invite link used to fetch
|
readonly client: TelegramClient,
|
||||||
* this preview
|
readonly invite: tl.RawChatInvite,
|
||||||
*/
|
/**
|
||||||
readonly link: string
|
* Original invite link used to fetch this preview
|
||||||
|
*/
|
||||||
constructor(client: TelegramClient, raw: tl.RawChatInvite, link: string) {
|
readonly link: string
|
||||||
this.client = client
|
) {
|
||||||
this.invite = raw
|
|
||||||
this.link = link
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { TelegramClient } from '../../client'
|
||||||
import { getMarkedPeerId, MaybeArray } from '@mtcute/core'
|
import { getMarkedPeerId, MaybeArray } from '@mtcute/core'
|
||||||
import { MtArgumentError, MtTypeAssertionError } from '../errors'
|
import { MtArgumentError, MtTypeAssertionError } from '../errors'
|
||||||
import { makeInspectable } from '../utils'
|
import { makeInspectable } from '../utils'
|
||||||
import { ChatsIndex, InputPeerLike, User, UsersIndex } from './index'
|
import { InputPeerLike, PeersIndex, User } from './index'
|
||||||
import { ChatLocation } from './chat-location'
|
import { ChatLocation } from './chat-location'
|
||||||
import { InputMediaLike } from '../media'
|
import { InputMediaLike } from '../media'
|
||||||
import { FormattedString } from '../parser'
|
import { FormattedString } from '../parser'
|
||||||
|
@ -33,9 +33,6 @@ export namespace Chat {
|
||||||
* A chat.
|
* A chat.
|
||||||
*/
|
*/
|
||||||
export class Chat {
|
export class Chat {
|
||||||
/** Telegram client used for this chat */
|
|
||||||
readonly client: TelegramClient
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Raw peer object that this {@link Chat} represents.
|
* Raw peer object that this {@link Chat} represents.
|
||||||
*/
|
*/
|
||||||
|
@ -46,15 +43,10 @@ export class Chat {
|
||||||
| tl.RawChatForbidden
|
| tl.RawChatForbidden
|
||||||
| tl.RawChannelForbidden
|
| tl.RawChannelForbidden
|
||||||
|
|
||||||
/**
|
|
||||||
* Raw full peer object that this {@link Chat} represents.
|
|
||||||
*/
|
|
||||||
readonly fullPeer?: tl.TypeUserFull | tl.TypeChatFull
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
client: TelegramClient,
|
readonly client: TelegramClient,
|
||||||
peer: tl.TypeUser | tl.TypeChat,
|
peer: tl.TypeUser | tl.TypeChat,
|
||||||
fullPeer?: tl.TypeUserFull | tl.TypeChatFull
|
readonly fullPeer?: tl.TypeUserFull | tl.TypeChatFull
|
||||||
) {
|
) {
|
||||||
if (!peer) throw new MtArgumentError('peer is not available')
|
if (!peer) throw new MtArgumentError('peer is not available')
|
||||||
|
|
||||||
|
@ -478,27 +470,25 @@ export class Chat {
|
||||||
static _parseFromMessage(
|
static _parseFromMessage(
|
||||||
client: TelegramClient,
|
client: TelegramClient,
|
||||||
message: tl.RawMessage | tl.RawMessageService,
|
message: tl.RawMessage | tl.RawMessageService,
|
||||||
users: UsersIndex,
|
peers: PeersIndex
|
||||||
chats: ChatsIndex
|
|
||||||
): Chat {
|
): Chat {
|
||||||
return Chat._parseFromPeer(client, message.peerId, users, chats)
|
return Chat._parseFromPeer(client, message.peerId, peers)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
static _parseFromPeer(
|
static _parseFromPeer(
|
||||||
client: TelegramClient,
|
client: TelegramClient,
|
||||||
peer: tl.TypePeer,
|
peer: tl.TypePeer,
|
||||||
users: UsersIndex,
|
peers: PeersIndex
|
||||||
chats: ChatsIndex
|
|
||||||
): Chat {
|
): Chat {
|
||||||
switch (peer._) {
|
switch (peer._) {
|
||||||
case 'peerUser':
|
case 'peerUser':
|
||||||
return new Chat(client, users[peer.userId])
|
return new Chat(client, peers.user(peer.userId))
|
||||||
case 'peerChat':
|
case 'peerChat':
|
||||||
return new Chat(client, chats[peer.chatId])
|
return new Chat(client, peers.chat(peer.chatId))
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Chat(client, chats[peer.channelId])
|
return new Chat(client, peers.chat(peer.channelId))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
|
|
|
@ -8,6 +8,7 @@ export * from './chat-member'
|
||||||
export * from './chat-event'
|
export * from './chat-event'
|
||||||
export * from './chat-invite-link'
|
export * from './chat-invite-link'
|
||||||
export * from './typing-status'
|
export * from './typing-status'
|
||||||
|
export * from './peers-index'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Peer types that have one-to-one relation to tl.Peer* types.
|
* Peer types that have one-to-one relation to tl.Peer* types.
|
||||||
|
@ -23,11 +24,14 @@ export type PeerType = 'user' | 'bot' | 'group' | 'channel' | 'supergroup'
|
||||||
/**
|
/**
|
||||||
* Type that can be used as an input peer
|
* Type that can be used as an input peer
|
||||||
* to most of the high-level methods. Can be:
|
* to most of the high-level methods. Can be:
|
||||||
* - `number`, representing peer's marked ID
|
* - `number`, representing peer's marked ID*
|
||||||
* - `string`, representing peer's username (w/out preceding `@`)
|
* - `string`, representing peer's username (w/out preceding `@`)
|
||||||
* - `string`, representing user's phone number (only for contacts)
|
* - `string`, representing user's phone number (only for contacts)
|
||||||
* - `"me"` and `"self"` which will be replaced with the current user/bot
|
* - `"me"` and `"self"` which will be replaced with the current user/bot
|
||||||
* - Raw TL object
|
* - Raw TL object
|
||||||
|
*
|
||||||
|
* > Telegram has moved to int64 IDs. Though, Levin [has confirmed](https://t.me/tdlibchat/25075)
|
||||||
|
* > that new IDs *will* still fit into int53, meaning JS integers are fine.
|
||||||
*/
|
*/
|
||||||
export type InputPeerLike =
|
export type InputPeerLike =
|
||||||
| string
|
| string
|
||||||
|
@ -36,6 +40,3 @@ export type InputPeerLike =
|
||||||
| tl.TypeInputPeer
|
| tl.TypeInputPeer
|
||||||
| tl.TypeInputUser
|
| tl.TypeInputUser
|
||||||
| tl.TypeInputChannel
|
| tl.TypeInputChannel
|
||||||
|
|
||||||
export type UsersIndex = Record<number, tl.TypeUser>
|
|
||||||
export type ChatsIndex = Record<number, tl.TypeChat>
|
|
||||||
|
|
48
packages/client/src/types/peers/peers-index.ts
Normal file
48
packages/client/src/types/peers/peers-index.ts
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import { tl } from '@mtcute/tl'
|
||||||
|
import { MtArgumentError } from '../errors'
|
||||||
|
|
||||||
|
const ERROR_MSG =
|
||||||
|
'Given peer is not available in this index. This is most likely an internal library error.'
|
||||||
|
|
||||||
|
export class PeersIndex {
|
||||||
|
readonly users: Record<number, tl.TypeUser> = Object.create(null)
|
||||||
|
readonly chats: Record<number, tl.TypeChat> = Object.create(null)
|
||||||
|
|
||||||
|
hasMin = false
|
||||||
|
|
||||||
|
static from(obj: {
|
||||||
|
users?: tl.TypeUser[]
|
||||||
|
chats?: tl.TypeChat[]
|
||||||
|
}): PeersIndex {
|
||||||
|
const index = new PeersIndex()
|
||||||
|
|
||||||
|
obj.users?.forEach((user) => {
|
||||||
|
index.users[user.id] = user
|
||||||
|
if ((user as any).min) index.hasMin = true
|
||||||
|
})
|
||||||
|
obj.chats?.forEach((chat) => {
|
||||||
|
index.chats[chat.id] = chat
|
||||||
|
if ((chat as any).min) index.hasMin = true
|
||||||
|
})
|
||||||
|
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
|
user(id: number): tl.TypeUser {
|
||||||
|
const r = this.users[id]
|
||||||
|
if (!r) {
|
||||||
|
throw new MtArgumentError(ERROR_MSG)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
chat(id: number): tl.TypeChat {
|
||||||
|
const r = this.chats[id]
|
||||||
|
if (!r) {
|
||||||
|
throw new MtArgumentError(ERROR_MSG)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue