2021-08-05 20:38:24 +03:00
|
|
|
import { tl } from '@mtcute/tl'
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-05-22 14:41:11 +03:00
|
|
|
import { BasicPeerType } from '../types'
|
2021-04-08 12:19:38 +03:00
|
|
|
|
2021-11-23 00:03:59 +03:00
|
|
|
// src: https://github.com/tdlib/td/blob/master/td/telegram/DialogId.h
|
|
|
|
const ZERO_CHANNEL_ID = -1000000000000
|
|
|
|
const ZERO_SECRET_CHAT_ID = -2000000000000
|
|
|
|
const MAX_SECRET_CHAT_ID = -1997852516353 // ZERO_SECRET_CHAT_ID + 0x7fffffff
|
|
|
|
// src: https://github.com/tdlib/td/blob/master/td/telegram/ChatId.h
|
|
|
|
// const MAX_CHAT_ID = 999999999999
|
|
|
|
const MIN_MARKED_CHAT_ID = -999999999999 // -MAX_CHAT_ID
|
|
|
|
// src: https://github.com/tdlib/td/blob/master/td/telegram/UserId.h
|
|
|
|
// MAX_USER_ID = (1ll << 40) - 1
|
|
|
|
const MAX_USER_ID = 1099511627775
|
|
|
|
// src: https://github.com/tdlib/td/blob/master/td/telegram/ChannelId.h
|
|
|
|
// the last (1 << 31) - 1 identifiers will be used for secret chat dialog identifiers
|
|
|
|
// MAX_CHANNEL_ID = 1000000000000ll - (1ll << 31)
|
|
|
|
// const MAX_CHANNEL_ID = 997852516352
|
|
|
|
const MIN_MARKED_CHANNEL_ID = -1997852516352 // ZERO_CHANNEL_ID - MAX_CHANNEL_ID
|
|
|
|
|
2022-08-29 16:22:57 +03:00
|
|
|
/**
|
|
|
|
* Add or remove channel marker from ID
|
|
|
|
*/
|
2021-11-23 00:03:59 +03:00
|
|
|
export function toggleChannelIdMark(id: number): number {
|
|
|
|
return ZERO_CHANNEL_ID - id
|
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the bare (non-marked) ID from a {@link tl.TypePeer}
|
|
|
|
*/
|
|
|
|
export function getBarePeerId(peer: tl.TypePeer): number {
|
2021-05-16 14:32:36 +03:00
|
|
|
switch (peer._) {
|
|
|
|
case 'peerUser':
|
|
|
|
return peer.userId
|
|
|
|
case 'peerChat':
|
|
|
|
return peer.chatId
|
|
|
|
case 'peerChannel':
|
|
|
|
return peer.channelId
|
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
}
|
|
|
|
|
2021-11-23 00:03:59 +03:00
|
|
|
// src: https://github.com/tdlib/td/blob/master/td/telegram/DialogId.cpp
|
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
/**
|
|
|
|
* Get the marked (non-bare) ID from a {@link tl.TypePeer}
|
|
|
|
*
|
|
|
|
* *Mark* is bot API compatible, which is:
|
|
|
|
* - ID stays the same for users
|
|
|
|
* - ID is negated for chats
|
2021-11-23 00:03:59 +03:00
|
|
|
* - ID is negated and `-1e12` is subtracted for channels
|
2021-04-08 12:19:38 +03:00
|
|
|
*/
|
2022-06-30 16:32:56 +03:00
|
|
|
export function getMarkedPeerId(peerId: number, peerType: BasicPeerType): number
|
2022-08-29 16:22:57 +03:00
|
|
|
export function getMarkedPeerId(peer: tl.TypePeer | tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel): number
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-04-08 12:19:38 +03:00
|
|
|
export function getMarkedPeerId(
|
2022-08-29 16:22:57 +03:00
|
|
|
peer: tl.TypePeer | tl.TypeInputPeer | tl.TypeInputUser | tl.TypeInputChannel | number,
|
2023-06-05 03:30:48 +03:00
|
|
|
peerType?: BasicPeerType,
|
2021-04-08 12:19:38 +03:00
|
|
|
): number {
|
|
|
|
if (typeof peer === 'number') {
|
2021-05-16 14:32:36 +03:00
|
|
|
switch (peerType) {
|
|
|
|
case 'user':
|
|
|
|
return peer
|
|
|
|
case 'chat':
|
|
|
|
return -peer
|
|
|
|
case 'channel':
|
2021-11-23 00:03:59 +03:00
|
|
|
return ZERO_CHANNEL_ID - peer
|
2021-05-16 14:32:36 +03:00
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
throw new Error('Invalid peer type')
|
|
|
|
}
|
|
|
|
|
2021-05-16 14:32:36 +03:00
|
|
|
switch (peer._) {
|
|
|
|
case 'peerUser':
|
|
|
|
case 'inputPeerUser':
|
2022-08-29 16:22:57 +03:00
|
|
|
case 'inputUser':
|
2021-05-16 14:32:36 +03:00
|
|
|
return peer.userId
|
|
|
|
case 'peerChat':
|
|
|
|
case 'inputPeerChat':
|
|
|
|
return -peer.chatId
|
|
|
|
case 'peerChannel':
|
|
|
|
case 'inputPeerChannel':
|
2022-08-29 16:22:57 +03:00
|
|
|
case 'inputChannel':
|
2021-11-23 00:03:59 +03:00
|
|
|
return ZERO_CHANNEL_ID - peer.channelId
|
2021-05-16 14:32:36 +03:00
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
|
|
|
|
throw new Error('Invalid peer')
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extract basic peer type from {@link tl.TypePeer} or its marked ID.
|
|
|
|
*/
|
|
|
|
export function getBasicPeerType(peer: tl.TypePeer | number): BasicPeerType {
|
|
|
|
if (typeof peer !== 'number') {
|
2021-05-16 14:32:36 +03:00
|
|
|
switch (peer._) {
|
|
|
|
case 'peerUser':
|
|
|
|
return 'user'
|
|
|
|
case 'peerChat':
|
|
|
|
return 'chat'
|
|
|
|
case 'peerChannel':
|
|
|
|
return 'channel'
|
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (peer < 0) {
|
2021-11-23 00:03:59 +03:00
|
|
|
if (MIN_MARKED_CHAT_ID <= peer) {
|
|
|
|
return 'chat'
|
|
|
|
}
|
|
|
|
|
2023-06-05 03:30:48 +03:00
|
|
|
if (MIN_MARKED_CHANNEL_ID <= peer && peer !== ZERO_CHANNEL_ID) { return 'channel' }
|
2021-11-23 00:03:59 +03:00
|
|
|
|
2022-06-30 16:32:56 +03:00
|
|
|
if (MAX_SECRET_CHAT_ID <= peer && peer !== ZERO_SECRET_CHAT_ID) {
|
2021-11-23 00:03:59 +03:00
|
|
|
// return 'secret'
|
|
|
|
throw new Error('Unsupported')
|
|
|
|
}
|
|
|
|
} else if (peer > 0 && peer <= MAX_USER_ID) {
|
2021-04-08 12:19:38 +03:00
|
|
|
return 'user'
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new Error(`Invalid marked peer id: ${peer}`)
|
|
|
|
}
|
|
|
|
|
2022-08-29 16:22:57 +03:00
|
|
|
/**
|
|
|
|
* Extract bare peer ID from marked ID.
|
|
|
|
*
|
|
|
|
* @param peerId Marked peer ID
|
|
|
|
*/
|
2021-04-08 12:19:38 +03:00
|
|
|
export function markedPeerIdToBare(peerId: number): number {
|
|
|
|
const type = getBasicPeerType(peerId)
|
2021-11-23 00:03:59 +03:00
|
|
|
|
2021-05-12 17:58:45 +03:00
|
|
|
switch (type) {
|
|
|
|
case 'user':
|
|
|
|
return peerId
|
|
|
|
case 'chat':
|
|
|
|
return -peerId
|
|
|
|
case 'channel':
|
2021-11-23 00:03:59 +03:00
|
|
|
return toggleChannelIdMark(peerId)
|
2021-05-12 17:58:45 +03:00
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
|
|
|
|
throw new Error('Invalid marked peer id')
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extracts all (cacheable) entities from a TlObject or a list of them.
|
|
|
|
* Only checks `.user`, `.chat`, `.channel`, `.users` and `.chats` properties
|
|
|
|
*/
|
|
|
|
export function* getAllPeersFrom(
|
2023-06-05 03:30:48 +03:00
|
|
|
obj: tl.TlObject | tl.TlObject[],
|
2021-06-06 15:20:41 +03:00
|
|
|
): Iterable<tl.TypeUser | tl.TypeChat> {
|
2021-04-18 16:23:25 +03:00
|
|
|
if (typeof obj !== 'object') return
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-08-14 12:37:22 +03:00
|
|
|
if (Array.isArray(obj)) {
|
|
|
|
for (const it of obj) {
|
|
|
|
yield* getAllPeersFrom(it)
|
|
|
|
}
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-08-14 12:37:22 +03:00
|
|
|
return
|
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
|
2021-05-16 14:32:36 +03:00
|
|
|
switch (obj._) {
|
|
|
|
case 'user':
|
|
|
|
case 'chat':
|
|
|
|
case 'channel':
|
|
|
|
case 'chatForbidden':
|
|
|
|
case 'channelForbidden':
|
|
|
|
yield obj
|
2023-06-05 03:30:48 +03:00
|
|
|
|
2021-05-16 14:32:36 +03:00
|
|
|
return
|
2021-04-18 16:23:25 +03:00
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
|
2021-04-18 16:23:25 +03:00
|
|
|
if (
|
|
|
|
'user' in obj &&
|
|
|
|
typeof obj.user === 'object' &&
|
|
|
|
obj.user._ === 'user'
|
|
|
|
) {
|
|
|
|
yield obj.user
|
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
|
2021-05-16 14:32:36 +03:00
|
|
|
if ('chat' in obj && typeof obj.chat === 'object') {
|
|
|
|
switch (obj.chat._) {
|
|
|
|
case 'chat':
|
|
|
|
case 'channel':
|
|
|
|
case 'chatForbidden':
|
|
|
|
case 'channelForbidden':
|
|
|
|
yield obj.chat
|
|
|
|
break
|
|
|
|
}
|
2021-04-18 16:23:25 +03:00
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
|
2021-05-16 14:32:36 +03:00
|
|
|
if ('channel' in obj && typeof obj.channel === 'object') {
|
|
|
|
switch (obj.channel._) {
|
|
|
|
case 'chat':
|
|
|
|
case 'channel':
|
|
|
|
case 'chatForbidden':
|
|
|
|
case 'channelForbidden':
|
|
|
|
yield obj.channel
|
|
|
|
break
|
|
|
|
}
|
2021-04-18 16:23:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if ('users' in obj && Array.isArray(obj.users) && obj.users.length) {
|
|
|
|
for (const user of obj.users) {
|
|
|
|
// .users is sometimes number[]
|
|
|
|
if (typeof user === 'object' && user._ === 'user') {
|
|
|
|
yield user
|
2021-04-08 12:19:38 +03:00
|
|
|
}
|
|
|
|
}
|
2021-04-18 16:23:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if ('chats' in obj && Array.isArray(obj.chats) && obj.chats.length) {
|
|
|
|
for (const chat of obj.chats) {
|
|
|
|
// .chats is sometimes number[]
|
2021-05-16 14:32:36 +03:00
|
|
|
if (typeof chat === 'object') {
|
|
|
|
switch (chat._) {
|
|
|
|
case 'chat':
|
|
|
|
case 'channel':
|
|
|
|
case 'chatForbidden':
|
|
|
|
case 'channelForbidden':
|
|
|
|
yield chat
|
|
|
|
break
|
2021-04-18 16:23:25 +03:00
|
|
|
}
|
2021-04-08 12:19:38 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|